1. Introduction
Java throws NumberFormatException – an unchecked exception – when it cannot convert a String to a number type.
Since it’s unchecked, Java does not force us to handle or declare it.
In this quick tutorial, we’ll describe and demonstrate what causes NumberFormatException in Java and how to avoid or deal with it.
2. Causes of NumberFormatException
There are various issues that cause NumberFormatException. For instance, some constructors and methods in Java throw this exception.
We’ll discuss most of them in the sections below.
2.1. Non-Numeric Data Passed to Constructor
Let’s look at an attempt to construct an Integer or Double object with non-numeric data.
Both of these statements will throw NumberFormatException:
Integer aIntegerObj = new Integer("one");
Double doubleDecimalObj = new Double("two.2");
Let’s see the stack trace we got when we passed invalid input “one” to the Integer constructor in line 1:
Exception in thread "main" java.lang.NumberFormatException: For input string: "one"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.<init>(Integer.java:867)
at MainClass.main(MainClass.java:11)
It threw NumberFormatException. The Integer constructor failed while trying to understand input using parseInt() internally.
The Java Number API doesn’t parse words into numbers, so we can correct the code by simply by changing it to an expected value:
Integer aIntegerObj = new Integer("1");
Double doubleDecimalObj = new Double("2.2");
2.2. Parsing Strings Containing Non-Numeric Data
Similar to Java’s support for parsing in the constructor, we’ve got dedicated parse methods like par**seInt(), parseDouble(), valueOf(), and decode()**.
If we try and do the same kinds of conversion with these:
int aIntPrim = Integer.parseInt("two");
double aDoublePrim = Double.parseDouble("two.two");
Integer aIntObj = Integer.valueOf("three");
Long decodedLong = Long.decode("64403L");
Then we’ll see the same kind of erroneous behavior.
And, we can fix them in similar ways:
int aIntPrim = Integer.parseInt("2");
double aDoublePrim = Double.parseDouble("2.2");
Integer aIntObj = Integer.valueOf("3");
Long decodedLong = Long.decode("64403");
2.3. Passing Strings With Extraneous Characters
Or, if we try to convert a string to a number with extraneous data in input, like whitespace or special characters:
Short shortInt = new Short("2 ");
int bIntPrim = Integer.parseInt("_6000");
Then, we’ll have the same issue as before.
We could correct these with a bit of string manipulation:
Short shortInt = new Short("2 ".trim());
int bIntPrim = Integer.parseInt("_6000".replaceAll("_", ""));
int bIntPrim = Integer.parseInt("-6000");
Note here in line 3 that negative numbers are allowed, using the hyphen character as a minus sign.
2.4. Locale-Specific Number Formats
Let’s see a special case of locale-specific numbers. In European regions, a comma may represent a decimal place. For example, “4000,1 ” may represent the decimal number “4000.1”.
By default, we’ll get NumberFormatException by trying to parse a value containing a comma:
double aDoublePrim = Double.parseDouble("4000,1");
We need to allow commas and avoid the exception in this case. To make this possible, Java needs to understand the comma here as a decimal.
We can allow commas for the European region and avoid the exception by using NumberFormat.
Let’s see it in action using the Locale for France as an example:
NumberFormat numberFormat = NumberFormat.getInstance(Locale.FRANCE);
Number parsedNumber = numberFormat.parse("4000,1");
assertEquals(4000.1, parsedNumber.doubleValue());
assertEquals(4000, parsedNumber.intValue());
3. Best Practices
Let’s talk about a few good practices that can help us to deal with NumberFormatException:
- Don’t try to convert alphabetic or special characters into numbers – the Java Number API cannot do that.
- We may want to validate an input string using regular expressions and throw the exception for the invalid characters.
- We can sanitize input against foreseeable known issues with methods like trim() and replaceAll().
- In some cases, special characters in input may be valid. So, we do special processing for that, using NumberFormat, for example, which supports numerous formats.
4. Conclusion
In this tutorial, we discussed NumberFormatException in Java and what causes it. Understanding this exception can help us to create more robust applications.
Furthermore, we learned strategies for avoiding the exception with some invalid input strings.
Finally, we saw a few best practices for dealing with NumberFormatException.
As usual, the source code used in the examples can be found over on GitHub.