java中拦截int溢出需在解析前主动校验范围,而非依赖运行时异常;推荐字符串字典序预检或long过渡校验,并在web层用自定义注解统一拦截,同时防范json反序列化、数据库读取及算术运算中的隐式溢出。

Java中拦截超出int取值范围(-2147483648 到 2147483647)的非法输入,关键不在于“运行时捕获溢出”(Java整数溢出默认静默),而在于在解析前主动校验字符串或数值是否落在有效范围内。防御性设计需覆盖常见输入场景:字符串转int、用户输入、JSON反序列化、数据库读取等。
字符串转int前做边界预校验
直接调用Integer.parseInt()遇到超限字符串会抛NumberFormatException,但异常成本高且不够精准(无法区分“abc”和“3000000000”)。应先判断字符串是否符合int范围:
- 检查字符串是否为空、仅含空白或带非法字符(如字母、多余符号)
- 按位比较字符串与
"-2147483648"或"2147483647"的字典序(注意负数处理) - 对正数:长度 > 10 → 超限;长度 == 10 → 逐字符比较是否 ≤ "2147483647"
- 对负数:去掉负号后长度 > 10 → 超限;长度 == 10 → 比较是否 ≤ "2147483648"
示例逻辑片段(不依赖异常):
String s = "2147483648";if (s == null || s.trim().isEmpty()) throw new IllegalArgumentException("输入为空");
s = s.trim();
boolean negative = s.charAt(0) == '-';
String numPart = negative ? s.substring(1) : s;
if (numPart.length() == 0) throw new IllegalArgumentException("格式错误");
if (numPart.length() > 10 || (numPart.length() == 10 && (negative ? numPart.compareTo("2147483648") > 0 : numPart.compareTo("2147483647") > 0))) {
throw new IllegalArgumentException("超出int取值范围");
}
使用Long过渡+范围检查(简洁可靠)
对可信度稍低但格式较规范的输入(如表单、API参数),可先转long再判断,避免字符串手工比对复杂逻辑:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 调用
Long.parseLong(s)(它支持更大范围,且对超long才抛异常) - 检查结果是否在
Integer.MIN_VALUE到Integer.MAX_VALUE之间 - 若越界,明确提示;否则安全转为
int
long value = Long.parseLong(s);
if (value Integer.MAX_VALUE) {
throw new IllegalArgumentException("输入超出int有效范围 [-2147483648, 2147483647]");
}
return (int) value;
} catch (NumberFormatException e) {
throw new IllegalArgumentException("非法数字格式", e);
}
在DTO/Controller层统一拦截(Spring Boot示例)
面向Web接口,应在参数绑定前拦截。结合注解与自定义校验器更工程化:
- 定义
@IntRange注解,标注在DTO字段上 - 实现
ConstraintValidator<intrange string></intrange>,复用前述字符串预校验逻辑 - Controller方法参数加
@Valid,配合@ExceptionHandler统一返回400错误
这样业务代码无需重复校验,且错误信息对前端友好(如"age必须是-2147483648~2147483647之间的整数")。
警惕自动类型提升与隐式转换场景
防御性编码还需覆盖易被忽略的“非字符串输入”路径:
-
JSON反序列化:Jackson默认将超int的数字转为
int并静默溢出(如3000000000→-1294967296)。启用DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS无效,正确做法是配置DeserializationFeature.FAIL_ON_INVALID_SUBTYPE不适用;推荐方案:自定义JsonDeserializer<integer></integer>,内部用Long解析后校验 -
数据库映射:JDBC读取BIGINT列到
int字段可能截断。在ORM层(如MyBatis TypeHandler)或实体类getter中加校验 -
算术中间结果:两个
int相加可能溢出。如需确保,改用Math.addExact(a, b)(溢出抛ArithmeticException)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










