
用 Math.addExact() 拦住整型溢出,核心就一条:它不让你“算错还装没事”,而是结果一越界就立刻抛 ArithmeticException。这不是事后检查,是加法执行中同步判定的硬性拦截。
只对 int 和 long 有效,别传错类型
这个方法只有两个重载:Math.addExact(int, int) 和 Math.addExact(long, long)。它不接受 short、byte、char 或包装类(如 Integer),也不支持 double 或混合类型。
- 传
short a = 10, b = 20;会自动提升为int,调用的是int版本 - 想用
long版本,至少一个操作数得带L后缀,比如Math.addExact(100L, x) - 别写
Math.addExact(Integer.valueOf(5), Integer.valueOf(10))——编译能过,但本质还是拆箱后走int版本,没额外好处
别让溢出发生在调用之前
常见错误是把普通加法塞进参数里,比如 Math.addExact(a + b, c)。这时 a + b 已经静默溢出,addExact 校验的是一个错误中间值,完全失效。
- 正确做法是链式调用:
Math.addExact(Math.addExact(a, b), c) - 多个数相加,用循环逐次校验:
sum = Math.addExact(sum, nextValue) - 如果数值来自用户输入或配置项,先做范围预判(如是否接近
MAX_VALUE)再决定是否启用addExact
异常必须显式处理,不能假装看不见
它抛的是 ArithmeticException,属于运行时异常,但语义明确——不是程序 bug,而是业务约束被突破。IDE 会标黄提醒你处理,别直接忽略。
- 关键计数器场景建议
throw new IllegalStateException(...)包裹原异常,带上上下文(如当前计数值、操作来源) - 批量处理时可捕获后记录日志、告警、跳过该条,避免整个批次失败
- 不要在
catch块里吞掉异常或返回默认值(如 0),那等于又回到“静默错误”老路
它快,但不是万能胶布
底层常被 JIT 内联为带 jo(jump on overflow)的汇编指令,性能损耗极小,比手写边界判断更可靠。但它只保“加法结果合法”,不保其他:
- 不检查参数是否为
null(基本类型不存在 null) - 不替代并发安全——多线程更新同一变量,仍需配合
AtomicInteger或锁 - 不解决循环索引、时间差、分页偏移等隐性溢出点,那些得单独建模校验

















