Java表达式溢出静默回绕,发生在运算过程而非赋值时;类型提升不保安全,乘法链须从long起,二分查找需防left+right溢出。

Java 表达式计算中,中间结果溢出是隐蔽但高频的问题——它不报错、不告警,只静默回绕,比如 Integer.MAX_VALUE + 1 变成 Integer.MIN_VALUE。关键在于:**溢出发生在运算过程中,不是在赋值时;类型提升不等于安全,而只是运算规则的起点**。
乘法链必须从 long 开始
Java 按左结合顺序逐项推导类型,整个表达式类型由最左边操作数决定。哪怕结果变量声明为 long,若所有字面量都是 int,中间仍全程用 算,溢出后才转 <code>long,已无意义。
- 错误写法:
long millis = 60 * 24 * 3600 * 1000;→ 实际算出889032704(溢出值) - 正确写法:
long millis = 60L * 24 * 3600 * 1000;或long millis = (long) 60 * 24 * 3600 * 1000; - 同理,计算微秒:
long micros = 24L * 60 * 60 * 1000 * 1000;(而非24 * 60 * 60 * 1000 * 1000L,位置错就无效)
外部输入参与运算前先升为 long
用户传入的 int 值(如分页 offset、持续分钟数、时间差)看似安全,但一旦数值变大,offset * pageSize 或 minutes * 60 * 1000 就可能在中间阶段溢出。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 别写:
new Date(now + lastTime * 60 * 1000) - 改写为:
new Date(now + (long) lastTime * 60 * 1000)或更优:TimeUnit.MINUTES.toMillis(lastTime) - 根本解法:接口参数直接定义为
long lastTime,从源头切断int参与数学运算
用 Math.exact 系列主动捕获溢出
不是所有场景都适合无脑升 long。当业务逻辑要求“溢出即失败”(如金额扣减、库存校验),应显式检查而非依赖静默环绕。
立即学习“Java免费学习笔记(深入)”;
-
Math.addExact(a, b)、Math.multiplyExact(a, b)、Math.toIntExact(longValue) - 溢出时抛
ArithmeticException,异常信息明确含 integer overflow,日志可直接定位 - 性能接近原生运算,JIT 有专门优化,不必担心开销
警惕隐性溢出点:索引、时间差、二分查找
溢出不只出现在大数相乘,这些地方常被忽略:
for (int i = start; i :若 <code>end == Integer.MAX_VALUE且step > 0,i加到最后会回绕成负数,导致死循环-
int diff = (int) (endTime - startTime):两个long时间戳相减可能超int范围,强制截断丢精度 → 改用long diff = endTime - startTime; - 二分查找中
int mid = (left + right) / 2:当left和right都接近MAX_VALUE时,left + right溢出 → 改为int mid = left + (right - left) / 2

















