ArithmeticException是Java中一个很典型的运行时异常,属于java.lang包下的Unchecked Exception,编译器不强制要求处理,可一旦触发,程序就会直接崩溃。最经典的表现就是在做整数除法时,控制台打印出java.lang.ArithmeticException: / by zero,很多初学者第一次看到都会疑惑:明明数学里除以零只是无意义,为什么Java要专门抛异常?这篇文章就来把这个异常的来龙去脉讲清楚,并给出几种实际可用的处理方案。

ArithmeticException的触发原理和常见场景
ArithmeticException的官方定义是:当出现异常的算术条件时抛出,比如整数运算中出现溢出或不合法的除法。在Java里,真正会触发它的高频场景其实不多,主要集中在整数除法和取模上。看下面这段代码:
public class Demo {
public static void main(String[] args) {
int a = 10;
int b = 0;
int result = a / b; // 这里直接抛出 ArithmeticException: / by zero
System.out.println(result);
}
}除了/ by zero,取模运算同样会中招:10 % 0会抛出相同的异常。还有一个容易被忽略的场景是非正规浮点数转整数时的精度问题,以及在BigDecimal做除法时没有指定精度和舍入模式,比如调用divide方法遇到除不尽的情况,会抛出ArithmeticException: Non-terminating decimal expansion,这个坑在金融计算中尤其常见。
有一个非常反直觉的知识点值得单独说明:浮点数除以零并不抛异常。写10.0 / 0会得到Infinity,-10.0 / 0得到-Infinity,0.0 / 0.0得到NaN。这是因为浮点数遵循IEEE 754标准,该标准明确定义了无穷大和非数值的表示方式,而int类型没有对应的表示手段,所以JVM只能选择抛异常来终止运算。理解这一点,在排查问题时能省不少时间,别看到日志里有除零异常就以为代码里写的是字面量0,很多时候是动态计算出来的值恰好等于零。
四种实用的处理方式
第一种也是最推荐的方式:前置校验。在执行除法前先判断除数是否为零,这是成本最低、逻辑最清晰的方案:
public static int safeDivide(int a, int b) {
if (b == 0) {
// 根据业务决定返回默认值或抛出自定义异常
return 0;
}
return a / b;
}第二种是try-catch捕获。适合除数来源不可控的场景,比如从用户输入、外部接口拿到的数值。捕获后可以记录日志并做降级处理:
try {
int result = total / count;
System.out.println("平均值为: " + result);
} catch (ArithmeticException e) {
System.err.println("计算失败,除数为零: " + e.getMessage());
// 降级逻辑,比如返回默认值或提示用户
}第三种是结合Optional把可能出错的结果包装起来,让调用方显式处理空值,避免异常直接炸到最外层:
import java.util.Optional;
public static Optional<Integer> divide(int a, int b) {
if (b == 0) {
return Optional.empty();
}
return Optional.of(a / b);
}第四种针对BigDecimal场景。做除法时务必传入精度和舍入模式,否则遇到1除以3这种无限小数就会抛异常:
import java.math.BigDecimal;
import java.math.RoundingMode;
BigDecimal a = new BigDecimal("1");
BigDecimal b = new BigDecimal("3");
// 指定保留10位小数,四舍五入
BigDecimal result = a.divide(b, 10, RoundingMode.HALF_UP);
System.out.println(result); // 输出 0.3333333333如何写出更健壮的算术代码
处理异常只是兜底,更重要的思路是把防御做在前面。对于可能为零的除数,建议在方法入口统一校验参数,配合Objects.requireNonNull风格的自定义断言工具类,让非法输入在边界处就被拦截。如果业务允许,也可以把除数从int换成double或BigDecimal,从类型层面规避整数除零的崩溃,但要注意浮点数会产生Infinity和NaN,后续判断同样不能少,比如用Double.isNaN和Double.isInfinite做检查。
另外要养成一个习惯:永远不要吞异常。catch块里只写一行e.printStackTrace()在生产环境等于没处理,日志要带上上下文信息,比如当时的分子分母值、来源参数等,方便事后追溯。团队协作中还可以把ArithmeticException统一纳入全局异常处理器(比如Spring项目中的@ControllerAdvice),对外返回友好提示而不是直接暴露堆栈。
最后总结一下核心要点:整数除法和取模遇到零除数会抛ArithmeticException,浮点数则返回特殊值;处理上优先做前置校验,不确定来源就用try-catch兜底,BigDecimal除法必须指定精度和舍入模式。掌握这些规则,这类异常基本不会再困扰你。
ArithmeticExceptionJava异常处理除零异常修改时间:2026-09-12 15:04:31