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 be 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;
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.