1. 简介
在 Java 编程中,当我们尝试将一个 字符串转换为数字类型(如 int
、double
等)时,如果字符串内容不合法,Java 会抛出 NumberFormatException
。
这是一个 非受检异常(unchecked exception),也就是说,编译器不会强制我们去处理它。但如果不处理,程序运行时就可能崩溃。
本文将带你了解:
- 什么情况下会抛出
NumberFormatException
- 常见的错误场景和示例
- 如何避免或处理这个异常
2. 导致 NumberFormatException 的常见原因
✅ 2.1 非数字字符串传入构造函数
Java 中很多数字类型的构造函数(如 Integer
、Double
)内部会调用解析方法。如果传入的字符串不是合法数字,就会抛出异常。
示例:
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
的实用建议:
不要尝试将字母或特殊字符转成数字
Java 的 Number API 不支持这种转换。使用正则表达式验证输入格式
例如判断是否为纯数字字符串:if (str.matches("\\d+")) { /* 合法 */ }
预处理输入字符串
使用trim()
、replaceAll()
等方法清理掉空格、特殊字符。处理本地化数字格式
使用NumberFormat
和Locale
支持多种数字格式,比如逗号作为小数点。
4. 总结
本文我们详细分析了 Java 中的 NumberFormatException
,包括:
- 常见触发场景
- 典型错误代码示例
- 对应的修复方式和最佳实践
通过合理验证和预处理输入字符串,我们可以有效避免这个异常,从而写出更健壮、稳定的 Java 应用。
完整示例代码可在 GitHub 上找到。