Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.
public boolean isNaN(String string){

@SuppressWarnings("unused")
BigDecimal bg = null;

try{

    bg = new BigDecimal(string);

}catch(Exception e){

    return true;
}

return false;
}

There is no native isNaN method for BigDecimal, the thing I don't like about this method is the suppressed warning. I never use the variable but only the constructor to see if it doesn't throw an exception and if it does I return the corresponding boolean.

What do you think?

share|improve this question

3 Answers 3

You said :

I never use the variable but only the constructor to see if it doesn't throw an exception

I would ask you, then why did you declare a variable at all ? You could have done :

public boolean isNaN(final String string) {
    try {
       new BigDecimal(string);
    } catch (final Exception e) {
        return true;
    }
    return false;
}

When you don't need a variable, don't declare it.

You should not catch Exception because it's too generic. What do you really want ? The constructor throw NumberFormatException if the argument is not valid, the better option would be to catch that one instead.

share|improve this answer
    
Seems I got a little lightheaded there. Thanks. –  overmann 12 hours ago
    
I'll try to have a nicer tone, but old habits die hard. Constructor are rarely use without a variable so it's easy to have an un-used variable. –  Marc-Andre 12 hours ago

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 nulls 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.

share|improve this answer
    
I would agree with you that managing 'NullPointerException' should be considered (which I did not). Your answer made me aware that there is a "special" value for NaN in Java. I think the op want a more general definition of NaN to what the abbreviation stand for, check if the input is a number or not. In fact, that was my interpretation of the question, I could be wrong. –  Marc-Andre 10 hours ago
2  
If one wants to handle both possibilities, one should write catch (NumberFormatException | NullPointerException e). Even better is to simply do if (string != null) before trying to create a BigDecimal. Catching all exceptions is convenient but it's almost never the right way to do things, because it obscures programmer mistakes. –  VGR 7 hours ago
    
@VGR I still mostly disagree, see my edit. Concerning obscuring if mistakes... yes, but I can't imagine any place leaving less place for mistakes. And guarding against mistakes in the standard library makes here no sense, as what you want to test is what the standard library does - i.e., my catch clause is tautologically correct. –  maaartinus 6 hours ago

Declaring the variable is entirely unnecessary, as has already been stated, but whether you do or not does not impact code clarity or performance, so I think it really comes down to personal preference.

The exception handling raises significantly more issues. For the most part, those have already been addressed, but I think the previous answers have skipped one major point of concern. Exceptions have their name for a reason; outside of unit tests, they should represent an exception to the normal flow of logic, and not play an active role in it.

The reason for this is that exceptions are really expensive, due to all the overhead in processing they imply. I would therefore replace the entire solution with RegEx that is as flexible as you need it to be and return whether or not it matches the input. For example:

import java.util.regex.*;

public class NumberTester
{
        private static Pattern p = Pattern.compile("-?\\d*(\\.\\d+)?");

        public static boolean test(String s)
        {
                return p.matcher(s).matches();
        }
}

The above is a basic example, so more work will have to go into the expression if you want to match something like scientific notation, or numbers with commas, but unless your actual goal is to write canBeParsedByBigDecimal(String s), I think a solution like this is significantly better.

share|improve this answer
    
Oops; just saw the RegEx footnote on @maaartinus's answer. I guess I'll leave this here anyway so the point is justified, since he didn't go into why the current method is slower. –  Millie 29 mins ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.