int运算溢出是算术结果超出范围导致静默回绕,强制转换则是类型映射时截断字节引发失真;二者均不报错但危害严重,需用math.exact方法、边界校验及合理类型选择主动防御。

int 运算溢出和强制转换不是同一类问题,但常被混为一谈。前者是算术过程失控,后者是类型映射失当——两者都可能产生看似合理、实则错误的数值,且均不自动报错。
int 运算溢出:静默回绕,逻辑崩塌
32 位有符号 int 的取值范围固定为 −2,147,483,648 到 2,147,483,647。一旦加、减、乘等运算结果超出该范围,Java 和 C/C++(默认模式)均不会抛异常,而是按补码规则“回绕”:
- 2147483647 + 1 → −2147483648
- −2147483648 − 1 → 2147483647
- 这类行为在 Java 中是明确定义的(确定性回绕),但在 C/C++ 中,有符号溢出属于未定义行为(编译器可任意处理)
- 典型风险场景:循环计数器越界、数组长度计算为负、时间差误判为倒计时、金融金额突变负值
强制转换的副作用:截断即失真,不检查即危险
强制转换(如 (int) longValue 或 (short) intValue)本身不做任何范围验证,仅保留目标类型的低位字节:
- long → int:直接丢弃高 32 位,2147483648L 强转后变成 −2147483648
- int → short:只留低 16 位,50000 变成 −15536(因 50000 的低 16 位补码解释为负数)
- 这种截断对无符号语义的数据(如数据库主键、雪花 ID、毫秒时间戳)尤为致命——负值会导致查不到记录、写入冲突或协议解析失败
- 编译器通常不警告,运行时也无提示,错误潜伏期长
安全替代方案:主动防御比事后调试更高效
不能依赖“大概不会超”,而应把边界检查或专用工具嵌入关键路径:
- 用 Math.toIntExact(long) 替代 (int) long:超限时明确抛 ArithmeticException
- 对 int 运算,优先使用 Math.addExact、multiplyExact 等方法,它们在溢出时立即中断而非静默出错
- 若必须手动检查(如性能敏感场景),加法判断用 a > 0 && b > Integer.MAX_VALUE − a,避免先算再判
- 外部输入(JSON、DB、HTTP 参数)一律视为不可信,转换前必做范围校验,尤其注意单位(毫秒 vs 秒)、协议约定与字段语义
根本原则:类型宽度要匹配业务语义,而非仅仅“够用”
int 不是万能整数容器。ID 字段、时间戳、累计值、索引偏移量等,若原始数据源可能超过 21 亿,就该从设计阶段选用 long 或 BigInteger;short 更适合明确限定在 ±3 万内的场景(如音频采样、状态码)。类型选择是架构决策,不是语法便利。











