NumberFormatException仅在字符串解析为数字时抛出,如Integer.parseInt()遇空串、非法字符、超范围值等;安全转换需校验后解析或用Optional封装;valueOf()与parseInt()异常行为一致,不提升容错性。

NumberFormatException到底在什么情况下抛出
它只发生在字符串转数字的解析阶段,比如 Integer.parseInt()、Long.parseLong()、Double.parseDouble() 这类静态方法遇到无法识别的格式时。不是所有类型转换都会触发——Integer.valueOf("123") 同样会抛,但强制类型转换如 (int) 123.5 属于编译期或运行期数值截断,跟它无关。
常见诱因包括:空字符串 ""、仅含空白字符(如 "\t \n")、带非法前缀("0x1A" 或 "+-123")、超出目标类型的取值范围("99999999999999999999" 转 int)。
怎么安全地做字符串到数字的转换
别直接调用 parseXxx(),先校验再解析,或者用更宽容的替代方案:
- 用
StringUtils.isNumeric()(Apache Commons Lang)判断是否为纯数字字符串,注意它不支持负号和小数点 - 正则预筛:
str != null && str.matches("-?\\d+(\\.\\d+)?"),但要注意浮点精度和科学计数法(如"1e5")不匹配 - 封装健壮工具方法,例如返回
Optional:
public static OptionalsafeParseInt(String s) { if (s == null || s.trim().isEmpty()) return Optional.empty(); try { return Optional.of(Integer.parseInt(s.trim())); } catch (NumberFormatException e) { return Optional.empty(); } }
为什么用valueOf()代替parseInt()有时也没用
Integer.valueOf() 内部其实调用了 parseInt(),只是多了一层缓存逻辑(对 -128 到 127 的整数复用对象)。所以当输入是 "abc" 或 " " 时,两者抛出的异常完全一样,都是 NumberFormatException。区别只在性能和对象引用上,不在容错能力。
立即学习“Java免费学习笔记(深入)”;
真正影响行为的是参数本身是否符合语法规范,而不是选哪个方法。别指望换一个包装方法就能绕过解析失败。
容易被忽略的边界情况
很多开发者以为 trim() 就万事大吉,但这些仍会触发异常:
-
"\u00A0"(不间断空格,Character.isWhitespace()返回 true,但trim()不处理) -
"123\u200E"(Unicode 方向控制符,肉眼不可见) -
"NaN"或"Infinity"——Double.parseDouble()接受它们,但Integer.parseInt()不接受任何非十进制整数字面量 - 不同 Locale 下的千位分隔符,如
"1,234"在英文环境里不是合法整数
如果数据来自外部输入(表单、文件、API),必须按实际语义清洗,不能只依赖通用 trim + parse 组合。










