Skip to content

parseLong vs parseDouble

Here’s a silly gotcha in the Java language. I’ve got a method that parses a String to an int and returns a default value if the String cannot be parsed:

int parseOrDefault(String val, int def) {
    try {
        return Integer.parseInt(val);            
    } catch (NumberFormatException e) {
        return def;
    }
}

I’ve got the same for other numeric types including long, double and float:

long parseOrDefault(String val, long def) {
    try {
        return Long.parseLong(val);
    } catch (NumberFormatException e) {
        return def;    
    }
}

float parseOrDefault(String val, float def) {
    try {
        return Float.parseFloat(val);
    } catch (NumberFormatException e) {
        return def;
    }
}

double parseOrDefault(String val, double def) {
    try {
        return Double.parseDouble(val);
    } catch (NumberFormatException e) {
        return def;
    }
}

I call each method with:

  1. A String that can be parsed;
  2. A String that cannot be parsed and;
  3. A null String
    PARSABLE = "42";
    UNPARSABLE = "forty-two";
    NULL = null;
    
    System.out.println("Parsing: " + PARSABLE);
    System.out.println(parser.parseOrDefault(PARSABLE, -1));
    System.out.println(parser.parseOrDefault(PARSABLE, -1L));
    System.out.println(parser.parseOrDefault(PARSABLE, -1.0F));
    System.out.println(parser.parseOrDefault(PARSABLE, -1.0D));
    
    System.out.println("Parsing: " + UNPARSABLE);
    System.out.println(parser.parseOrDefault(UNPARSABLE, -1));
    System.out.println(parser.parseOrDefault(UNPARSABLE, -1L));
    System.out.println(parser.parseOrDefault(UNPARSABLE, -1.0F));
    System.out.println(parser.parseOrDefault(UNPARSABLE, -1.0D));
    
    System.out.println("Parsing: " + NULL);
    System.out.println(parser.parseOrDefault(NULL, -1));
    System.out.println(parser.parseOrDefault(NULL, -1L));
    System.out.println(parser.parseOrDefault(NULL, -1.0F));
    System.out.println(parser.parseOrDefault(NULL, -1.0D));
    

    The result is:

    Parsing: 42
    42
    42
    42.0
    42.0
    Parsing: forty-two
    -1
    -1
    -1.0
    -1.0
    Parsing: null
    -1
    -1
    Exception in thread "main" java.lang.NullPointerException
    	at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1838)
    	at java.base/jdk.internal.math.FloatingDecimal.parseFloat(FloatingDecimal.java:122)
    	at java.base/java.lang.Float.parseFloat(Float.java:455)
    	at Parser.parseOrDefault(Parser.java:47)
    	at Parser.main(Parser.java:25)
    
    

    Float.parseFloat() and Double.parseDouble() are not consistent with Integer.parseInt() and Long.parseLong(). The integer types Integer and Long throw NumberFormatException when provided with a null String. The floating point types Float and Double throw NullPointerException. Both NumberFormatException and NullPointerException are unchecked RuntimeExceptions so you might miss this mistake until it fails at runtime.

    If you want to safely parse Float and Double, remember to check for null or catch NullPointerException.

    float parseOrDefault(String val, float def) {
        try {
            return Float.parseFloat(val);
        } catch (NumberFormatException | NullPointerException e) {
            return def;
        }
    }
    
    double parseOrDefault(String val, double def) {
        try {
            return Double.parseDouble(val);
        } catch (NumberFormatException | NullPointerException e) {
            return def;
        }
    }
    
    Published inJava Basics

    Be First to Comment

    Leave a Reply

    Your email address will not be published. Required fields are marked *