To complement the other answer:
I wouldn't call it isNaN
as it's by far not obvious, that you mean "BigDecimal-NaN".
Actually, "isNaN" is confusing, even when we know, it deals with BigDecimal
. NaN
is a special double
value, which you will NOT get when you try Double.parse("foobar")
. Moreover, there's no Double#isNan(String)
. So I'd call it "isValidBigDecimal".
Speed could be a concern, when you plan to use it like
if (isNan(s)) bd = new BigDecimal(s);
as you parse it twice. What about tryParse
returning null
on failure?
I strongly disagree with this remark:
You should not catch Exception because it's too generic. What do you really want ?
I guess, the OP wants to know if a given string is a valid BigDecimal
. If it's not, they'll get an Exception
and this is a good reason to catch Exception
here. When the code was long, then I'd also advise against catching "so much", but there is a single statement here, and the question is "does it succeed or not".
Note that, despite Javadoc, an NPE gets also thrown. Not catching it may be OK as null
s are a curse and it's better to disallow them everywhere, but this decision should be done explicitly.
I disagree with the comment
If one wants to handle both possibilities, one should write catch (NumberFormatException | NullPointerException e).
The question isNaN
should answer is "Will it return a number or throw?". This makes catching Exception
correct by definition. Anything else is like a search for an alternative representation of 42. The dogma "never catch Exception" should be extended by "... unless it's exactly what you need".
So, my favorite (non-optimized) solution is
public BigDecimal tryParseBigDecimal(String string) {
if (string == null) {
return null;
}
try {
return new BigDecimal(string);
} catch (Exception e) {
assert e instanceof NumberFormatException || e instanceof NullPointerException : e;
return null;
}
}
public boolean isValidBigDecimal(String string) {
return tryParseBigDecimal(string) != null;
}
I've added an assert
expressing out expectations. This way I'd get notified if something really strange happened.
A much faster solution could be to use the regex
[-+]?(?:\d+\.\d*|\.\d+)(?:[eE][-+]?\d+)?
but you can imagine that it opens quite some room for bugs.
UPDATE
In the comments I was told that it is irresponsible to recommend (especially to newer programmers) that it is common to catch Exception
. That's true and that's why I'm writing this. My rules are
- Be always as specific as possible. Never catch too much, especially
- never catch a superclass when you expect a special exception
- make you try-catch blocks as small as possible
- Always react appropriately to exceptions. Especially, never swallow them. Most of the time, declaring them in the
throws
clause is the best.
That all said, I still think that my solution is best if you need a method checking if a given String can be parsed as BigDecimal
(and need no optimizations).
Update
Actually, catching Exception
is not necessary as RuntimeException
would do. This covers the documented NumberFormatException
, the undocumented NullPointerException
and all other undocumented exceptions which may get thrown. It doesn't cover checked exception, but they can't occur (unless someone uses dirty hacks), so it's fine. I still insist that catching less is wrong.
BigDecimal
or any other parsing class offer a mechanism that doesn't throw exceptions? Perhaps use Apache NumberUtilsisNumber
: commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/… . If you must use your own implementation peek at the source forisNumber
. \$\endgroup\$!isNaN()
) are annoying and require you to think for a second,isNaN
is "standard" in several programming languages. \$\endgroup\$