java中int溢出会静默回绕,需用math.addexact等方法捕获异常、升级long类型或前置边界检查来防范。

Java中int类型溢出不会报错,而是静默回绕——比如Integer.MAX_VALUE + 1直接变成Integer.MIN_VALUE。这种行为在金额计算、索引运算、权限校验等场景可能引发严重逻辑错误甚至安全漏洞,必须主动防范。
用Math.exact系列方法捕获溢出
Java 8起提供Math.addExact、Math.multiplyExact等方法,一旦溢出就抛ArithmeticException,避免静默错误。
- 加法:
Math.addExact(a, b) - 减法:
Math.subtractExact(a, b) - 乘法:
Math.multiplyExact(a, b) - 除法和取模不在此列,需单独校验分母或符号
适合日常业务逻辑,代码简洁且语义明确。例如:
try {
int result = Math.multiplyExact(100000, 100000); // 抛异常
} catch (ArithmeticException e) {
// 处理溢出:降级、告警、转BigInteger等
}
升级为long类型扩大安全边界
int范围是±21亿,而long范围达±9.2×10¹⁸。若预估结果不会超过long上限,直接改用long是最轻量的规避方式。
- 声明变量时用
long替代int(注意字面量加L后缀) - 运算中间结果也应保持为
long,避免先算int再赋值 - 注意:long仍会溢出,仅降低概率;高风险场景建议配合
Math.multiplyExact使用
示例:
// 错误:先用int乘再转long,已溢出 int a = 200000, b = 200000; long bad = a * b; // 实际执行int乘法,结果错误 <p>// 正确:至少一个操作数为long long good = (long) a * b;</p>
对关键运算做前置边界检查
在性能敏感或无法修改调用栈的场景,可手动判断是否溢出。核心思路是:运算前验证结果是否仍在目标类型范围内。
- 加法检查:
a > 0 && b > 0 && a > Integer.MAX_VALUE - b - 减法检查:
a 0 && a - 乘法检查更复杂,需分符号组合判断,推荐复用
Math.multiplyExact或直接用BigInteger
适用于底层库、高频循环或JNI交互等对异常开销敏感的场合。
用BigInteger处理任意精度需求
当数值范围完全不可预估(如阶乘、密码学运算、超大ID生成),java.math.BigInteger是唯一可靠选择。
- 支持无限精度整数,无溢出风险
- 所有运算方法(
add、multiply等)均返回新对象,线程安全 - 代价是内存占用高、运算慢,不适合高频简单计算
示例:
BigInteger a = BigInteger.valueOf(100000); BigInteger b = BigInteger.valueOf(100000); BigInteger result = a.multiply(b); // 绝对安全
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











