核心一句话:
NumberFormatException
是在将非数字字符串转换为int
或Integer
时抛出的运行时异常,主要发生在Integer.parseInt()
和Integer.valueOf()
方法中,必须通过try-catch
或预校验进行安全处理。
一、异常定义
- 异常类:
java.lang.NumberFormatException
- 继承自:
IllegalArgumentException
→RuntimeException
- 是否检查异常:否(运行时异常,编译器不强制要求捕获)
- 何时抛出:当字符串无法解析为有效整数时
二、哪些方法会抛出 NumberFormatException
?
方法 | 说明 |
---|---|
Integer.parseInt(String s) |
将字符串转为 int 基本类型 |
Integer.valueOf(String s) |
将字符串转为 Integer 对象(内部调用 parseInt ) |
new Integer(String s) |
已废弃,但也会抛出 |
✅ 所有基于字符串的整数解析操作都可能触发此异常。
三、常见触发场景(附示例)
❌ 场景 1:空字符串或 null
Integer.parseInt(null); // ❌ 抛出 NPE(空指针)
Integer.parseInt(""); // ❌ NumberFormatException
❌ 场景 2:非数字字符
Integer.parseInt("abc"); // ❌
Integer.parseInt("12.34"); // ❌ 小数点不是整数
Integer.parseInt("12a"); // ❌ 混合字符
Integer.parseInt(" "); // ❌ 空白字符
❌ 场景 3:超出 int
范围
Integer.parseInt("9999999999"); // ❌ 超出 int 最大值 2147483647
Integer.parseInt("-9999999999"); // ❌ 超出最小值 -2147483648
❌ 场景 4:带空格(无自动 trim)
Integer.parseInt(" 123 "); // ❌ 抛异常(除非使用 trim)
四、异常处理方式(3种主流方案)
✅ 方案 1:try-catch
捕获异常(最常用)
public static int parseSafe(String str) {
try {
return Integer.parseInt(str);
} catch (NumberFormatException e) {
System.err.println("解析失败: " + str);
return 0; // 或抛出自定义异常、返回 Optional 等
}
}
// 使用
int num = parseSafe("abc"); // 返回 0,不崩溃
✅ 优点:灵活,可自定义默认值或错误处理逻辑
⚠️ 缺点:性能略低(异常开销大),不适用于高频解析
✅ 方案 2:预校验 + try-catch
(推荐用于高频场景)
public static boolean isInteger(String str) {
if (str == null || str.trim().isEmpty()) return false;
str = str.trim();
int startIndex = 0;
if (str.charAt(0) == '-' || str.charAt(0) == '+') startIndex = 1;
if (startIndex >= str.length()) return false; // 只有符号
for (int i = startIndex; i < str.length(); i++) {
if (!Character.isDigit(str.charAt(i))) {
return false;
}
}
// 可选:检查是否超出 int 范围(较复杂,可省略)
try {
Integer.parseInt(str);
return true;
} catch (NumberFormatException e) {
return false;
}
}
// 使用
String input = "123";
if (isInteger(input)) {
int num = Integer.parseInt(input);
}
✅ 优点:避免频繁抛异常,性能更好
⚠️ 缺点:代码略复杂
✅ 方案 3:返回 Optional<Integer>
(函数式编程风格)
public static Optional<Integer> tryParse(String str) {
try {
return Optional.of(Integer.parseInt(str));
} catch (NumberFormatException e) {
return Optional.empty();
}
}
// 使用
Optional<Integer> result = tryParse("abc");
if (result.isPresent()) {
int num = result.get();
} else {
System.out.println("解析失败");
}
// 或使用 orElse
int num = tryParse("abc").orElse(0);
✅ 优点:语义清晰,避免
null
,适合链式调用
⚠️ 缺点:Java 8+ 才支持
五、最佳实践 ✅
1. 永远不要假设输入是合法数字
// ❌ 危险
int num = Integer.parseInt(userInput);
// ✅ 安全
int num = tryParse(userInput).orElse(DEFAULT_VALUE);
2. 对用户输入、配置文件、网络数据做严格校验
String portStr = config.getProperty("port");
int port = tryParse(portStr).filter(p -> p > 0 && p < 65536)
.orElseThrow(() -> new ConfigException("端口无效"));
3. 避免在循环中频繁抛异常
// ❌ 高频抛异常,性能差
for (String s : strings) {
try {
int n = Integer.parseInt(s);
} catch (NumberFormatException e) { }
}
// ✅ 先校验
for (String s : strings) {
if (isInteger(s)) {
int n = Integer.parseInt(s);
}
}
4. 使用 Apache Commons 或 Guava(生产环境推荐)
使用 Apache Commons Lang:
import org.apache.commons.lang3.math.NumberUtils;
int num = NumberUtils.toInt("abc", 0); // 解析失败返回 0
boolean isNum = NumberUtils.isCreatable("123"); // 安全校验
使用 Google Guava:
import com.google.common.primitives.Ints;
Integer num = Ints.tryParse("abc"); // 返回 null 而非抛异常
✅ 推荐在项目中引入这些库,避免重复造轮子。
六、自定义安全解析工具类(推荐)
public class SafeIntParser {
public static int parseInt(String str, int defaultValue) {
try {
return Integer.parseInt(str.trim());
} catch (NumberFormatException | NullPointerException e) {
return defaultValue;
}
}
public static Optional<Integer> tryParse(String str) {
try {
return Optional.of(Integer.parseInt(str.trim()));
} catch (NumberFormatException | NullPointerException e) {
return Optional.empty();
}
}
public static boolean isValidInteger(String str) {
if (str == null || (str = str.trim()).isEmpty()) return false;
try {
Integer.parseInt(str);
return true;
} catch (NumberFormatException e) {
return false;
}
}
}
七、常见错误 ❌
错误 | 正确做法 |
---|---|
Integer.parseInt(null) |
先判空 |
Integer.parseInt(" 123 ") |
先 trim() |
用 == 比较解析结果 |
用 .equals() 或 Objects.equals() |
在 switch 中使用 Integer |
先判空或转 int |
八、总结:快速掌握要点 ✅
项目 | 内容 |
---|---|
异常来源 | parseInt , valueOf , new Integer(String) |
常见原因 | 空、非数字、超出范围、格式错误 |
处理方式 | try-catch 、预校验、Optional 、工具库 |
最佳实践 | 不信输入、预校验、用 Optional 或默认值 |
推荐工具 | NumberUtils.toInt() , Ints.tryParse() |
性能建议 | 避免在循环中频繁抛异常 |
安全建议 | 所有外部输入都需校验 |
🎯 一句话总结:
NumberFormatException
是字符串转整数时的“拦路虎”,必须通过try-catch
、预校验或使用Optional
/工具库进行安全处理,永远不要假设输入是合法数字,尤其是在处理用户输入、配置或网络数据时。