Math.multiplyExact() 是 Java 8 引入的安全乘法方法,溢出时抛 ArithmeticException;普通乘法会静默回绕(如 Integer.MAX_VALUE * 2 得 -2),易引发逻辑错误。

Math.multiplyExact() 是 Java 8 引入的安全乘法工具方法,专门用于在整数乘法运算中自动检测溢出,并在发生溢出时立即抛出 ArithmeticException,避免静默错误或不可预期的结果。
它和普通乘法(*)有什么区别?
普通乘法(如 a * b)在 int 或 long 范围外会“回绕”(wrap around),比如:
-
Integer.MAX_VALUE * 2结果是-2(不是报错,而是溢出后取低 32 位) - 这种行为隐蔽且易引发逻辑 bug,尤其在金融、计费、索引计算等场景中很危险
-
Math.multiplyExact(a, b)遇到同样情况会直接抛出ArithmeticException("integer overflow")
怎么正确使用 Math.multiplyExact()?
该方法有两组重载,分别处理 int 和 long 类型:
-
Math.multiplyExact(int x, int y)—— 输入输出都是int,溢出即抛异常 -
Math.multiplyExact(long x, long y)—— 输入输出都是long,同样严格检查 - 不支持
short/byte/char,传入前需显式提升为int - 不能用于浮点数(
float/double),Java 没有对应的安全浮点乘法方法
实际使用建议与注意事项
推荐在以下场景优先使用 multiplyExact:
- 数组/列表索引计算(例如
row * width + col),防止越界访问 - 内存分配估算(如
size * elementSize),避免因溢出导致分配过小内存 - 计费、积分、金额相关逻辑(即使当前数据小,未来扩展可能触发溢出)
- 配合 try-catch 主动处理异常,而不是依赖默认回绕行为
示例:
try {
int result = Math.multiplyExact(1000000, 3000); // 安全:结果 3_000_000_000 > Integer.MAX_VALUE → 抛异常
} catch (ArithmeticException e) {
System.err.println("检测到整数溢出:" + e.getMessage());
// 可降级为 long 运算:Math.multiplyExact((long)a, (long)b)
}
替代方案与延伸思考
若需更灵活的溢出控制,可考虑:
- 用
long临时计算再检查范围(但不如multiplyExact简洁) - 使用 Guava 的
IntMath.checkedMultiply()(功能类似,但属第三方库) - 对性能极度敏感的循环内,应权衡异常开销;但多数业务代码中,安全性远大于微小性能损失
记住:它不是万能的,但它是让溢出问题“浮出水面”的最轻量级手段之一。










