java 8起math类提供溢出安全方法,如addexact、tointexact等,越界即抛arithmeticexception,非静默绕回;仅支持int/long运算与long转int,不防浮点溢出、并发问题或隐性索引溢出。

Java 的 Math 类从 Java 8 起提供了一组“溢出安全”的数值操作方法,它们不是“强转”,而是**带校验的精确运算与转换**——值一越界就抛 ArithmeticException,不静默绕回、不截断丢数。用对了,就是最轻量、最可靠的越界拦截手段。
用 Math.addExact 等方法做加减乘运算拦截
这些方法在结果超出目标类型范围时立即中断,不是事后检查,而是运算过程中同步判定:
-
Math.addExact(int, int)和Math.addExact(long, long):只对这两个重载有效;传short或byte会自动提升为int,走的是int版本 -
Math.multiplyExact和Math.subtractExact同理,也只支持int/long - 别写
Math.addExact(a + b, c)——a + b已静默溢出,校验失去意义;应链式调用:Math.addExact(Math.addExact(a, b), c) - 批量累加推荐循环逐次校验:
sum = Math.addExact(sum, next),异常可捕获后记录、告警或跳过
用 Math.toIntExact 安全转 long → int
这是替代 (int)someLong 的标准做法,语义清晰、行为确定:
- 值在
[Integer.MIN_VALUE, Integer.MAX_VALUE]内 → 返回对应int - 超出范围 → 抛
ArithmeticException(不是IllegalArgumentException),日志里直接看到 “integer overflow” - 比手写
if (v MAX)更简洁、不易漏边界,也避免重复逻辑 - 注意:它不处理
null(long是基本类型),但若源是Long对象,需先判空再调用
用 Math.round 配合 toIntExact 处理浮点转整数
浮点数转整数有双重风险:小数部分截断 + 数值越界。不能只靠 (int)val 或 Math.round(val):
-
Math.round(double)返回long,若直接(int)Math.round(x),可能因long超int范围而静默溢出 - 安全链路是:
int result = Math.toIntExact(Math.round(x)) - 若
x可能为NaN或无穷大,Math.round会返回Long.MIN_VALUE或Long.MAX_VALUE,仍会触发toIntExact的溢出异常,正好一并捕获 - 业务上要明确:这里用的是四舍五入;若需截断,应改用
Math.floor(x)或Math.ceil(x),再套toIntExact
关键提醒:它不覆盖所有越界场景
Math 的 Exact 方法是利器,但不是万能补丁:
- 不防浮点溢出:
double + double出Infinity不会触发这些异常 - 不保并发安全:多线程更新同一变量,仍需锁或原子类
- 不替代上下文判断:比如时间戳毫秒值,得先确认单位是否该除以 1000,再考虑转
int - 不处理隐性索引溢出:
for (int i = start; i 中,若 <code>end == Integer.MAX_VALUE,i可能绕回负数导致死循环——这类需单独建模防护











