1. Introduction
1.绪论
Java throws NumberFormatException – an unchecked exception – when it cannot convert a String to a number type.
当Java无法将字符串转换为数字类型时,它会抛出NumberFormatException – 一个未检查的异常。
Since it’s unchecked, Java does not force us to handle or declare it.
由于它是未检查的,Java并不强迫我们处理或声明它。
In this quick tutorial, we’ll describe and demonstrate what causes NumberFormatException in Java and how to avoid or deal with it.
在这个快速教程中,我们将描述并演示Java中什么原因导致NumberFormatException以及如何避免或处理它。
2. Causes of NumberFormatException
2.造成NumberFormatException的原因
There are various issues that cause NumberFormatException. For instance, some constructors and methods in Java throw this exception.
有很多问题会导致NumberFormatException。例如,Java中的一些构造函数和方法会抛出这种异常。
We’ll discuss most of them in the sections below.
我们将在下面的章节中讨论其中的大部分。
2.1. Non-Numeric Data Passed to Constructor
2.1.传递给构造函数的非数字数据
Let’s look at an attempt to construct an Integer or Double object with non-numeric data.
让我们看看试图用非数字数据构造一个Integer或Double对象的情况。
Both of these statements will throw NumberFormatException:
这两个语句都会抛出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:
让我们看看我们在第1行向Integer构造函数传递无效输入 “one “时得到的堆栈跟踪。
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.
它抛出了NumberFormatException。Integer构造函数在试图理解内部使用parseInt()的输入时失败。
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:
Java Number API并不将单词解析为数字,所以我们可以通过简单地将其改为预期值来纠正代码。
Integer aIntegerObj = new Integer("1");
Double doubleDecimalObj = new Double("2.2");
2.2. Parsing Strings Containing Non-Numeric Data
2.2.解析包含非数字数据的字符串
Similar to Java’s support for parsing in the constructor, we’ve got dedicated parse methods like parseInt(), parseDouble(), valueOf(), and decode().
与Java在构造函数中对解析的支持类似,我们有专门的解析方法,如parseInt()、parseDouble()、valueOf(),以及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
2.3.传递带有多余字符的字符串
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.
注意这里的第3行,负数是允许的,使用连字符作为减号。
2.4. Locale-Specific Number Formats
2.4.当地特定的号码格式
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”.
让我们来看看当地特有的数字的特殊情况。在欧洲地区,一个逗号可能代表一个小数位。例如,”4000,1 “可能代表小数点后的数字 “4000.1”。
By default, we’ll get NumberFormatException by trying to parse a value containing a comma:
默认情况下,我们试图解析一个包含逗号的值,会得到NumberFormatException。
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.
我们需要允许逗号,避免在这种情况下出现异常。为了使之成为可能,Java需要将这里的逗号理解为小数。
We can allow commas for the European region and avoid the exception by using NumberFormat.
我们可以通过使用NumberFormat来允许欧洲地区使用逗号,并避免出现异常。
Let’s see it in action using the Locale for France as an example:
让我们以法国的Locale为例,看看它的作用。
NumberFormat numberFormat = NumberFormat.getInstance(Locale.FRANCE);
Number parsedNumber = numberFormat.parse("4000,1");
assertEquals(4000.1, parsedNumber.doubleValue());
assertEquals(4000, parsedNumber.intValue());
3. Best Practices
3.最佳实践
Let’s talk about a few good practices that can help us to deal with NumberFormatException:
让我们来谈谈一些可以帮助我们处理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
4.总结
In this tutorial, we discussed NumberFormatException in Java and what causes it. Understanding this exception can help us to create more robust applications.
在本教程中,我们讨论了Java中的NumberFormatException以及它的原因。了解这种异常可以帮助我们创建更健壮的应用程序。
Furthermore, we learned strategies for avoiding the exception with some invalid input strings.
此外,我们还学到了避免某些无效输入字符串出现异常的策略。
Finally, we saw a few best practices for dealing with NumberFormatException.
最后,我们看到了处理NumberFormatException的一些最佳实践。
As usual, the source code used in the examples can be found over on GitHub.
像往常一样,在例子中使用的源代码可以在GitHub上找到超过。