Java中long乘法溢出需预判:b>0时a≤Long.MAX_VALUE/b且a≥Long.MIN_VALUE/b;b<0时a≥Long.MAX_VALUE/b且a≤Long.MIN_VALUE/b;否则抛ArithmeticException。

Java中long类型取值范围是-2⁶³到2⁶³−1(即-9223372036854775808L ~ 9223372036854775807L)。直接相乘可能溢出,但Java不会抛异常,而是静默回绕。要安全检测,不能依赖结果再判断,而应在运算前做数学预判。
利用数学边界提前判断是否溢出
两个long数a和b相乘,若不溢出,则必须满足:
当b > 0时:a ≤ Long.MAX_VALUE / b 且 a ≥ Long.MIN_VALUE / b
当b
当b == 0时,结果恒为0,不会溢出
- 关键点:用整数除法做阈值比较,避免实际乘法发生
- 注意Long.MIN_VALUE / b在b = -1时会溢出(因为|Long.MIN_VALUE|比Long.MAX_VALUE大1),需单独处理
- 推荐用Math.multiplyExact(long, long)(Java 8+),它内部已实现该逻辑并抛ArithmeticException
手写安全乘法方法(兼容老版本JDK)
以下是一个可直接使用的静态工具方法:
public static long safeMultiply(long a, long b) {
if (b == 0) return 0;
if (a > 0 && b > 0 && a > Long.MAX_VALUE / b) throw new ArithmeticException("long overflow");
if (a < 0 && b < 0 && a < Long.MAX_VALUE / b) throw new ArithmeticException("long overflow");
if (a > 0 && b < 0 && b < Long.MIN_VALUE / a) throw new ArithmeticException("long overflow");
if (a < 0 && b > 0 && a < Long.MIN_VALUE / b) throw new ArithmeticException("long overflow");
return a * b;
}说明:
• 四种符号组合分别判断,覆盖所有溢出场景
• 使用整数除法(截断向零)是安全的,因我们只关心是否“越过边界”
• 不用浮点运算,避免精度丢失和性能开销
使用Math.multiplyExact简化开发
Java 8起提供标准API,语义清晰、经过充分测试:
try {
long result = Math.multiplyExact(a, b);
// 正常使用result
} catch (ArithmeticException e) {
// 处理溢出,例如降级为BigInteger或抛业务异常
}- 底层逻辑与手写方法一致,但更可靠
- 适合多数业务场景,无需重复造轮子
- 若需自定义溢出行为(如返回null、默认值或日志记录),再封装一层即可
扩展:支持返回Optional或布尔标记
有些场景不希望抛异常,可用返回值方式:
立即学习“Java免费学习笔记(深入)”;
public static Optional<Long> tryMultiply(long a, long b) {
try {
return Optional.of(Math.multiplyExact(a, b));
} catch (ArithmeticException e) {
return Optional.empty();
}
}或更轻量的布尔检查方法:
public static boolean willOverflow(long a, long b) {
try {
Math.multiplyExact(a, b);
return false;
} catch (ArithmeticException e) {
return true;
}
}按需选择——异常适合错误场景,Optional适合函数式链式调用,布尔值适合快速校验。


















