java运算符不处理溢出,需人工防控:合理选类型(如long+l后缀)、用math.*exact()抛异常、大数用biginteger、输入前置校验。

Java 中运算符本身不处理溢出——%、+、* 等运算符完全按操作数类型执行,溢出时静默回绕,不会报错也不会预警。真正有效的防御,是人在写代码时主动控制类型、检查边界或切换计算载体。
用对数据类型,从源头掐断溢出可能
很多溢出不是因为数太大,而是因为“算的时候还是 int”。比如 int a = 100000; int b = 100000; int c = a * b;,乘法全程在 int 范围内算,结果直接错成 1410065408(不是 100 亿)。解决方法不是等出错再补救,而是让运算一开始就在更大容器里进行:
- 把关键变量声明为
long,且所有字面量加L后缀:如long millis = 60L * 24 * 3600 * 1000; - 外部输入(如配置、API 参数)参与计算前先强转:
(long) userMinutes * 60 * 1000 - 避免“声明 long,但中间全是 int 运算”的假安全写法,例如
long x = a * b;(a、b 是 int)仍是危险的
用 Math.*Exact() 主动捕获,让溢出变成可处理的异常
Java 8+ 提供了 Math.addExact()、Math.multiplyExact() 等方法,它们和普通运算符行为一致,唯一区别是:一旦溢出,立刻抛 ArithmeticException。这对需要强校验的场景(如计费、库存、权限判断)非常实用:
- 替代
a + b→Math.addExact(a, b) - 替代
a * b→Math.multiplyExact(a, b) - 异常信息明确含 “integer overflow”,日志里一眼可查,比静默错值好调试得多
大数场景别硬扛,直接上 BigInteger
当数值可能远超 long 上限(比如 10^9 + 7 的平方、阶乘、密码学模幂),靠升级类型或检查都难兜住。此时 BigInteger 不是备选,而是标准解法:
- 构造:用
BigInteger.valueOf(x)或new BigInteger(String),避免从溢出的 long 强转 - 运算:全部调用方法,如
a.multiply(b)、a.mod(m),不支持+、%运算符 - 注意:不要用
b.longValue()验证结果,它会再次溢出;应打印b.toString()或用equals()比较
字符串输入要前置校验,别等 parseInt 再崩溃
用户输了个 "3000000000",Integer.parseInt() 会直接抛 NumberFormatException,但这属于事后补救,且异常成本高、信息模糊。更优做法是在解析前就判断是否越界:
- 长度判断:正数字符串长度 > 10,或负数去掉负号后长度 > 10 → 直接拒绝
- 字典序比较:长度 == 10 时,正数比
"2147483647"大、负数去掉负号后比"2147483648"大 → 越界 - 或走“Long 过渡”路线:
long v = Long.parseLong(s); if (v Integer.MAX_VALUE) throw ...
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











