接口传上来一个age字段,看着是数字,直接Integer.parseInt就抛NumberFormatException。断点一看值是带空格的18,前面还夹了个全角空格。字符串转int看着一行代码,边界情况比想象的多。

parseInt 和 valueOf 的区别

Integer.parseInt返回基本类型int,Integer.valueOf返回Integer对象,内部调的也是parseInt,只是多包一层。两者遇到非法字符都抛NumberFormatException,遇到null抛的也是NumberFormatException而不是空指针,这点很多人记错。valueOf对-128到127有缓存,包装对象比较时别用等号。

先清洗再转换

trim只去半角和小于等于空格的字符,全角空格要去掉得用replace。带千分位逗号的,先replace掉逗号。带小数点的不能直接parseInt,得先Double.parseDouble再取整,或者用BigDecimal。前面有正号能识别,带货币符号会直接报错。

String s = raw.trim(); if (s.isEmpty()) { return 0; } int v = Integer.parseInt(s);

进制与超大数

parseInt传第二个参数可以按指定进制解析,范围2到36。字符串是0x开头时别直接传16,会报错,先substring截掉前两位。超过21亿的数用parseInt必溢出,虽然不抛异常但结果是错的,改用Long.parseLong,再大就用BigInteger的构造函数。

更稳妥的写法

  • 可能为空:先判null和空串,给一个默认值。
  • 可能非法:用try catch包住,或者配正则先做格式预校验。
  • 表单输入:用Scanner的hasNextInt先探,或用Commons的NumberUtils.toInt,非法时返回默认值不抛异常。

对外接口一律按不可信输入处理,转换失败要返回明确的错误码,别让异常直接冒到框架层变成500。