Java NumberFormatException异常详解

作者 | 2020年4月8日

1. 前言

Java中的NumberFormatException异常在字符串解析为数字失败时抛出。该异常是一个不受检查的(unchecked)异常,这意味着Java不会强制要求在编译时处理与声明它,因此该异常可能会在运行时抛出。

在本文中我们将演示NumberFormatException异常的产生原因以及对应的处理方法。

2. NumberFormatException的产生原因

引发NumberFormatException异常的原因有许多,比如,某些构造函数会抛出该异常,下面我们将讨论几个常见的原因。

2.1 通过构造函数传递传递非法字符串

我们来看一下使用非法字符串来构造一个IntegerDouble对象会发生什么。

下面这两条语句会引发NumberFormatException异常:

Integer aIntegerObj = new Integer("one");
Double doubleDecimalObj = new Double("two.2");

让我们来看一下new Integer("one")引起的NumberFormatException异常堆栈:

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)

由上可见在构造器内部调用了Integer.parseInt()方法试图把字符串解析为整数。

Integer.parseInt()方法不能把单词解析为数字,所以需要改变一下输入:

Integer aIntegerObj = new Integer("1");
Double doubleDecimalObj = new Double("2.2");

2.2 解析非法字符串为数字

除了使用构造器来把字符串解析为数字之外,我们可以直接调用一些专用的方法来把字符串解析为数字,这些方法包括:parseInt()parseDouble()valueOf()decode()

如果像下面这样使用这些方法,则会引发NumberFormatException异常。

int aIntPrim = Integer.parseInt("two");
double aDoublePrim = Double.parseDouble("two.two");
Integer aIntObj = Integer.valueOf("three");
Long decodedLong = Long.decode("64403L");

如果要避免NumberFormatException异常则需要传入合法的字符串作为参数:

int aIntPrim = Integer.parseInt("2");
double aDoublePrim = Double.parseDouble("2.2");
Integer aIntObj = Integer.valueOf("3");
Long decodedLong = Long.decode("64403");

2.2 字符串中包含特殊字符

还有一种情况是,被解析的字符串中存在特殊字符,例如包含空格或者下划线:

Short shortInt = new Short("2 ");
int bIntPrim = Integer.parseInt("_6000");

这也会导致抛出NumberFormatException异常。

为此,可能需要使用一些手段来修正这些特殊字符:

Short shortInt = new Short("2 ".trim());
int bIntPrim = Integer.parseInt("_6000".replaceAll("_", ""));
int bIntPrim = Integer.parseInt("-6000");

2.4 本地化的数字格式

接着来看一个更特殊的情况:本地化的数字格式。在欧洲地区,一个逗号可能会表示一个小数位,例如:4000,1表示4000.1

默认情况下,如果我们尝试把这样的字符串解析为数字则会引发NumberFormatException异常:

double aDoublePrim = Double.parseDouble("4000,1");

因此,我们需要使用NumberFormat来设置区域为欧洲来避免该异常。

下面我们来把地区设为法国:

NumberFormat numberFormat = NumberFormat.getInstance(Locale.FRANCE);
Number parsedNumber = numberFormat.parse("4000,1");
assertEquals(4000.1, parsedNumber.doubleValue());
assertEquals(4000, parsedNumber.intValue());

3. 最佳实践

下面来看一下能够帮我们处理NumberFormatException异常的最佳实践:

  • 避免将字母或特殊字符转为数字
  • 转换之前先使用正则表达式验证输入参数
  • 使用replaceAll()trim()方法来移除特殊字符
  • 某些情况下一些特殊的字符可能是合法的,可以使用NumberFormat来处理这些符号

4. 总结

在本文中,我们讨论了在Java中引起NumberFormatException异常的原因,明白这些原因能帮我们创建更具有健壮性的程序。

此外,我们学习了对特殊字符进行处理的一些方法,来避免特殊字符所引发的NumberFormatException异常。

最后,总结了一下处理NumberFormatException异常的最佳实践。

发表评论

电子邮件地址不会被公开。 必填项已用*标注