← 中文资源

简体中文版本

Java ArithmeticException: / by zero — 整数除法陷阱

通过防护整数除数、区分整数与浮点除法,并处理空聚合,修复 “/ by zero” ArithmeticException。

阅读英文原文

症状

本篇调试指南针对“Java ArithmeticException: / by zero — 整数除法陷阱”。内容涵盖可观察的症状、可复现的诊断路径、根本原因、具体修复方式,以及如何验证修复并防止回归。

可观察到的症状包括:

  • java.lang.ArithmeticException: / by zero
  • 同样的表达式用 double 返回 Infinity 而非抛异常
  • 平均或百分比函数在空输入上失败

诊断

先在隔离环境中复现故障,再按顺序执行以下检查,逐步缩小范围。

步骤 1

jshell -q <<'EOF'
try { int r = 10 / 0; } catch (ArithmeticException e) { System.out.println(e); }
EOF

整数除法抛异常;10.0/0 得到 Infinity,证明类型影响行为。

步骤 2

grep -rn "/ [a-zA-Z].*size()\|% .*count" src/main/java

审查来自 size 或 count 的除数,可找出未防护的路径。

常见诱因(按出现频率排序):

  • 整数除法或取模的除数可能为零
  • 对空集合求平均,长度为 0
  • 对某路径上为零的变量做整数取模

根因

整数除法与取模的除数为零时未定义并抛 ArithmeticException。浮点除法按 IEEE 754 返回 NaN 或 Infinity,因此该缺陷专属于整数运算。

修复

除法前防护除数,为空聚合返回明确定义的哨兵值,并在可接受 Infinity/NaN 语义时明确选择 double。

注意:未定义平均返回 0 可能被误读;应返回 OptionalDouble.empty() 表示缺失。

public static OptionalDouble average(int[] values) {
    if (values.length == 0) return OptionalDouble.empty(); // no division
    long sum = 0;
    for (int v : values) sum += v;
    return OptionalDouble.of((double) sum / values.length);
}

int divisor = 0;
int safe = divisor == 0 ? 0 : 100 / divisor; // guarded

验证

用零除数重跑,确认无异常且得到预期哨兵;为零与非零除数补充测试。

修复后补充一条回归测试,复现原始症状,防止问题再次出现。

这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。