1. 简介

在 Java 编程中,当我们尝试将一个 字符串转换为数字类型(如 intdouble 等)时,如果字符串内容不合法,Java 会抛出 NumberFormatException

这是一个 非受检异常(unchecked exception),也就是说,编译器不会强制我们去处理它。但如果不处理,程序运行时就可能崩溃。

本文将带你了解:

  • 什么情况下会抛出 NumberFormatException
  • 常见的错误场景和示例
  • 如何避免或处理这个异常

2. 导致 NumberFormatException 的常见原因

✅ 2.1 非数字字符串传入构造函数

Java 中很多数字类型的构造函数(如 IntegerDouble)内部会调用解析方法。如果传入的字符串不是合法数字,就会抛出异常。

示例:

Integer aIntegerObj = new Integer("one");      // ❌ 抛出 NumberFormatException
Double doubleDecimalObj = new Double("two.2"); // ❌ 同样抛异常

异常堆栈如下:

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 aIntegerObj = new Integer("1");
Double doubleDecimalObj = new Double("2.2");

✅ 2.2 使用 parse 方法解析非法字符串

Java 提供了多个用于字符串解析的静态方法,例如:

  • Integer.parseInt()
  • Double.parseDouble()
  • Integer.valueOf()
  • Long.decode()

如果我们尝试解析非法字符串:

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.3 含有非法字符的字符串

有时候我们传入的字符串中可能包含 空格、下划线、逗号等特殊字符,这些也会导致解析失败。

示例:

Short shortInt = new Short("2 ");         // ❌ 空格
int bIntPrim = Integer.parseInt("_6000"); // ❌ 下划线

修复方法:使用字符串处理方法清除干扰字符:

Short shortInt = new Short("2 ".trim());                    // 去空格
int bIntPrim = Integer.parseInt("_6000".replaceAll("_", "")); // 去下划线
int cIntPrim = Integer.parseInt("-6000");                   // ✅ 负号是允许的

✅ 2.4 本地化数字格式问题

在某些国家(如法国),逗号(,)用于表示小数点。例如,字符串 "4000,1" 表示 4000.1

如果我们直接使用 Double.parseDouble("4000,1"),会抛出异常。

double aDoublePrim = Double.parseDouble("4000,1"); // ❌ 抛异常

解决方案:使用 NumberFormat 并指定 Locale

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

3. 最佳实践

以下是一些避免 NumberFormatException 的实用建议:

  1. 不要尝试将字母或特殊字符转成数字
    Java 的 Number API 不支持这种转换。

  2. 使用正则表达式验证输入格式
    例如判断是否为纯数字字符串:

    if (str.matches("\\d+")) { /* 合法 */ }
    
  3. 预处理输入字符串
    使用 trim()replaceAll() 等方法清理掉空格、特殊字符。

  4. 处理本地化数字格式
    使用 NumberFormatLocale 支持多种数字格式,比如逗号作为小数点。


4. 总结

本文我们详细分析了 Java 中的 NumberFormatException,包括:

  • 常见触发场景
  • 典型错误代码示例
  • 对应的修复方式和最佳实践

通过合理验证和预处理输入字符串,我们可以有效避免这个异常,从而写出更健壮、稳定的 Java 应用。

完整示例代码可在 GitHub 上找到。