Java Math.addExact() 方法详解


方法定义

Math.addExact() 是 Java 8 引入的精确算术方法,用于执行安全的加法运算:

// 整数版本
public static int addExact(int x, int y)

// 长整数版本
public static long addExact(long x, long y)

功能说明

  • 精确加法:计算两个参数的和
  • 溢出检测:当结果超出数据类型范围时抛出 ArithmeticException
  • 支持类型int (范围: -2³¹ 到 2³¹-1) 和 long (范围: -2⁶³ 到 2⁶³-1)
  • 异常行为:溢出时立即抛出异常,避免产生错误值

示例代码

// 正常加法
int safeSum = Math.addExact(100, 200);  // 300
long largeSum = Math.addExact(10_000_000L, 20_000_000L);  // 30_000_000L

// 溢出案例
try {
    int overflow = Math.addExact(Integer.MAX_VALUE, 1);  // 抛出 ArithmeticException
} catch (ArithmeticException e) {
    System.out.println("整数溢出!");
}

try {
    long minOverflow = Math.addExact(Long.MIN_VALUE, -1);  // 抛出 ArithmeticException
} catch (ArithmeticException e) {
    System.out.println("长整数溢出!");
}

使用技巧

  1. 安全边界检查:在可能产生溢出的计算前使用
    int calculate(int a, int b) {
        try {
            return Math.addExact(a, b);
        } catch (ArithmeticException e) {
            // 返回安全值或使用long计算
            return (long)a + b > Integer.MAX_VALUE ? Integer.MAX_VALUE : Integer.MIN_VALUE;
        }
    }
    
  2. 循环累加防护:保护累加操作
    int sum = 0;
    for (int value : values) {
        sum = Math.addExact(sum, value);  // 防止累积溢出
    }
    

常见错误

  1. 忽略异常处理

    // 危险:可能导致程序崩溃
    int total = Math.addExact(Integer.MAX_VALUE, 100);
    
  2. 混淆数据类型

    // 编译错误:参数类型不匹配
    long result = Math.addExact(100, 2_000_000_000L);
    // 正确写法:Math.addExact(100L, 2_000_000_000L)
    
  3. 错误处理溢出

    // 错误:先溢出后捕获
    try {
        int sum = a + b;  // 可能已溢出但无异常
    } catch (Exception e) { /* 不会触发 */ }
    

注意事项

  1. 性能影响:相比普通加法有额外检查开销(约2-3倍),在紧密循环中需评估性能
  2. 浮点数不支持:仅适用于整数类型(int/long)
  3. 负数溢出Integer.MIN_VALUE + (-1) 也会触发溢出
  4. 字面量陷阱:大数字字面量默认为int,可能导致编译错误
    Math.addExact(2_000_000_000, 1_500_000_000);  // 字面量超出int范围
    

最佳实践与性能优化

  1. 热点代码优化:在性能关键路径且确定无溢出时使用普通加法
    // 低风险场景使用普通加法
    int sum = a + b;  // 当a,b绝对值均小于1亿时
    
  2. 批量处理:对大数组使用分段检测
    long segmentSum = 0;
    for (int i = 0; i < 1000; i++) {
        segmentSum = Math.addExact(segmentSum, data[i]);
    }
    
  3. 提前检测:对极大值进行预判
    if (b > 0 && a > Integer.MAX_VALUE - b) {
        throw new ArithmeticException("Overflow detected");
    }
    int sum = a + b;
    
  4. 替代方案:使用更大数据类型
    long safeResult = (long) a + b;
    if (safeResult > Integer.MAX_VALUE) {
        // 处理溢出
    }
    

总结

关键点 说明
核心功能 提供溢出保护的加法运算
异常机制 溢出时抛出 ArithmeticException
适用场景 财务计算、安全关键系统、未知输入处理
性能权衡 牺牲少量性能换取安全性
替代方案 普通加法(性能好但危险)、手动溢出检查(复杂但灵活)
版本要求 Java 8+

实践口诀

精确加法防溢出,addExact 来守护;
异常处理不可少,性能热点需评估;
大数运算用 long,安全边界要牢记。

使用 Math.addExact() 可有效防止整数溢出导致的隐蔽错误,特别适用于处理用户输入或不可控数据源的计算场景。在性能敏感区域,建议结合手动溢出检查或使用 long 类型过渡。