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:
- A
Stringthat can be parsed; - A
Stringthat cannot be parsed and; - A
nullString
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;
}
}
Be First to Comment