Java字符串转数字需据场景选方法:parseInt/valueOf对非法输入抛异常,NumberUtils.toInt可设默认值且自动trim;注意null、空格、进制、精度及框架隐式转换风险。

Java 中字符串转数字不是“选一个方法就行”,而是得看输入是否可信、是否允许异常、要不要处理边界值、目标类型是什么——不同场景下,Integer.parseInt、Integer.valueOf、NumberUtils.toInt 等行为差异很大,用错轻则抛异常,重则静默返回默认值导致逻辑错误。
字符串转 int:parseXXX 和 valueOf 的关键区别
Integer.parseInt("123") 返回 int 基本类型,遇到空串、null 或非数字字符直接抛 NumberFormatException;Integer.valueOf("123") 返回 Integer 对象,底层复用缓存(-128 到 127),但同样对非法输入抛异常。二者在合法输入下性能接近,但语义不同:前者适合数值计算,后者适合集合存储或泛型场景。
常见踩坑点:
- 传
null给parseInt—— 必抛NullPointerException(因为先判 null 再调用) - 传空字符串
""—— 两者都抛NumberFormatException,不是返回 0 - 传带空格的
" 123 "—— 同样失败,需先trim()
安全转换:避免异常的替代方案
生产环境不建议裸用 parseInt,尤其当输入来自用户或外部接口时。推荐用 Apache Commons Lang 的 NumberUtils.toInt(String, int):
立即学习“Java免费学习笔记(深入)”;
int num = NumberUtils.toInt("abc", -1); // 返回 -1,不抛异常
int num2 = NumberUtils.toInt(" 456 ", 0); // 自动 trim,返回 456
它内部做了 try-catch + trim(),且支持指定默认值。注意:NumberUtils 对 null 和空串也返回默认值,这点和原生方法本质不同。
自定义安全转换可参考:
- 用
Optional.ofNullable(str).map(s -> s.trim()).filter(s -> !s.isEmpty()).map(Integer::parseInt).orElse(0) - 或更轻量:先
str == null || str.trim().isEmpty()判空,再parseInt
转其他数字类型:long/double/BigInteger 的注意事项
Long.parseLong("999999999999") 可以,但用 Integer.parseInt 会溢出抛异常;Double.parseDouble("1.23e-4") 支持科学计数法,而整型方法不支持;new BigInteger("12345678901234567890") 是唯一能无损表示超长整数的方式。
关键差异:
-
Float.parseFloat("NaN")返回Float.NaN,不抛异常;Integer.parseInt("NaN")抛异常 -
BigDecimal构造函数接受字符串(如new BigDecimal("0.1")),但绝不能用double构造(new BigDecimal(0.1)会精度丢失) -
Long.parseLong("0x1F", 16)支持进制参数,parseInt同样支持,但默认是十进制
JSON 或配置解析中的隐式转换风险
Spring Boot 的 @Value("${port:8080}") 或 Jackson 反序列化时,字符串字段标注 @JsonFormat 或用 Integer 类型接收,框架会自动调用 valueOf。但若配置值为 "null" 字符串(不是 JSON null),可能被转成 Integer.valueOf("null") —— 直接炸。
这类场景必须确认数据源格式,必要时加自定义 Converter 或用 @JsonDeserialize 控制反序列化逻辑。别依赖框架“自动猜”。
最易被忽略的是:所有基于 parseXXX 的转换都要求字符串**完全由数字字符构成(可带正负号)**,任何额外字符(包括不可见的 Unicode 空格、BOM 头)都会失败。调试时用 str.codePoints().forEach(System.out::println) 查看真实字节组成,比肉眼判断可靠得多。











