空指针异常(nullpointerexception)是java中因对null引用调用方法、访问字段、自动拆箱或链式调用中断而抛出的运行时异常;算术异常(arithmeticexception)则主要由整数除零或bigdecimal无舍入除法等数学运算错误引发,二者均需从变量使用、方法设计和数据校验三层面提前防御。

空指针异常(NullPointerException)和算术异常(ArithmeticException)是Java中最常触发、也最容易规避的两类运行时异常。它们不需强制捕获,但一旦发生,往往直接中断执行流程。防范核心不是“出了再修”,而是从变量使用、方法设计、数据校验三个层面提前堵住漏洞。
空指针异常:别让null偷偷参与运算
它本质是试图对一个值为 null 的引用做操作——调用方法、访问字段、自动拆箱、链式调用中断等。常见却不容忽视:
-
字符串比较别写 s.equals("abc"),改用
"abc".equals(s),避免 s 为 null 时崩溃 - 包装类型慎拆箱:Integer i = null; int j = i; → 直接抛 NPE;应先判空或用 Optional
-
集合返回值别返回 null:方法本该返回 List
,就返回 Collections.emptyList(),而非 null -
链式调用加保险:user.getAddress().getCity().getName() 容易断在任一环;可改用 Optional 链式安全提取:
Optional.ofNullable(user).map(User::getAddress).map(Address::getCity).map(City::getName).orElse("未知")
算术异常:除零和大数溢出要盯紧
ArithmeticException 主要出现在整数除法分母为 0,或某些严格数学运算(如 BigDecimal 除不尽且未指定舍入模式)中。浮点数除零不会抛此异常(结果为 Infinity 或 NaN),所以重点在 int/long 类型的 / 和 % 运算:
- 除法前必校验分母:if (divisor != 0) { result = dividend / divisor; },尤其参数来自用户输入或配置时
-
用 BigDecimal 做精确计算时,避免无舍入除法:不要写
bigA.divide(bigB),应写bigA.divide(bigB, 2, RoundingMode.HALF_UP) -
注意负数取模行为:Java 中
-5 % 2 == -1,若业务逻辑依赖非负余数,应手动归正:((a % b) + b) % b
统一防御策略:从编码习惯到工程实践
单靠 if 判空或 try-catch 不是长久之计。系统性防范更可靠:
-
@NonNull / @Nullable 注解驱动:在方法参数、返回值上标注(如 Lombok 的
@NonNull或 JetBrains 的@NotNull),配合 IDE 实时提示 - 构造函数强制初始化:关键字段在构造时赋值,避免对象处于“半初始化”状态
- 单元测试覆盖边界值:专门构造 null 输入、0 除数、负数模数等用例,验证逻辑健壮性
- 静态分析工具接入 CI:如 SpotBugs(原 FindBugs)能扫描潜在 NPE 路径,SonarQube 可设规则拦截高风险代码提交
这两类异常背后反映的是数据契约是否清晰、边界是否被尊重。写代码时多问一句“这个值真可能为空吗?”“这个数真可能为零吗?”,比事后调试快得多。











