Java 异常

一、异常的第一性原理

1.1 异常的本质

在任何编程语言中,异常机制的本质只有一句话:

异常 = 跨函数边界的错误传播机制

它解决的根本问题是:

当程序执行路径上出现“非常规情况”时,如何优雅地打断正常控制流,并把错误信息传递给合适的处理者。


1.2 为什么需要异常

在异常机制出现之前,程序处理错误主要依赖:

这些方式的本质问题是:

错误处理逻辑会污染正常业务逻辑

异常机制的价值在于:

方式 关注点
返回值 调用方必须显式判断
异常 将“错误处理”与“业务逻辑”解耦

异常让程序结构从:

业务逻辑 + 大量 if 判断

变为:

业务逻辑主路径
+ 独立的异常处理路径

1.3 异常的三大核心特征

异常机制在本质上提供了三个能力:

  1. **中断当前流程**
  2. **携带错误上下文**
  3. **跨层传播**

这三点共同决定了:

异常不是“错误本身”,而是“错误处理的组织机制”。


二、Java 异常模型

2.1 Java 的异常类型体系

在 Java 中,异常体系是一棵类型树:

Object
 └── Throwable
     ├── Error
     └── Exception
          ├── Checked Exception
          └── RuntimeException

两个根概念

类型 本质
Error JVM 层面无法恢复的问题
Exception 程序逻辑层面可处理的问题

2.2 Checked vs Unchecked 的本质

Java 将异常分为两类:

维度 Checked Exception Runtime Exception
编译器要求 必须处理 可不处理
设计意图 强制调用方感知 表示程序缺陷
可恢复性 更偏可恢复 更偏不可恢复

核心区别不是“能否处理”,而是:

是否需要通过类型系统强制上层关注


2.3 Java 异常体系的设计哲学

Java 的异常模型背后有两个核心设计思想:

  1. **让业务代码更干净**
  2. **让错误传播更显式**

但实践中也暴露出问题:

因此在工程实践中:

RuntimeException 往往成为主流选择


三、异常的多维度认知模型

为了避免“分类混乱”,需要把异常放在不同维度下理解。


3.1 语法维度

这是:

Java 语言机制层面的划分


3.2 来源维度

来源 示例
业务异常 未授权、余额不足
系统异常 空指针、数组越界
基础设施异常 网络超时、数据库异常

3.3 可恢复性维度

类型 策略
可恢复 重试、降级
不可恢复 快速失败

3.4 处理边界维度

范围 方式
模块内部 直接处理
服务边界 转换为错误码
跨系统 封装为 Result

四、异常处理的核心原则

4.1 异常处理的本质矛盾

异常机制的最大问题是:

异常处理是复杂度的放大器

不合理的异常设计,会让系统变得:


4.2 三条核心原则

原则一:就近处理


原则二:语义稳定

对外接口的异常必须稳定:

接口的异常变化 = 接口契约变化


原则三:最小惊讶


五、工程实践模型

5.1 分层异常架构

一个稳定系统中的异常结构应为:

Controller
   ↓
Service -> BusinessException
   ↓
DAO -> InfrastructureException

5.2 异常转换模式

不同层次之间应进行异常转换:

层次 策略
DAO 转为数据访问异常
Service 转为业务异常
API 转为错误码

5.3 Result 模式

在跨系统调用中:

❗ 不应该直接抛异常

而应该使用:

Result<T> {
  code
  message
  data
}

原因:

  1. 防止调用方漏捕获
  2. 更利于序列化
  3. 更稳定的接口契约

六、异常使用规范

6.1 try-catch 的本质

try {
    // 正常路径
} catch (SpecificException e) {
    // 异常路径
} finally {
    // 资源清理
}

其本质是:

把控制流一分为二:


6.2 捕获原则


6.3 finally 语义

finally 的语义是:

资源一致性保证,而非业务逻辑承载

因此:


七、异常的性能本质

7.1 两个层次的开销

行为 开销
try-catch 本身 很小
真正抛异常 很大

7.2 为什么异常昂贵

因为抛异常时 JVM 需要:

这是一个“重型操作”。


7.3 工程启示


八、系统设计中的异常策略

8.1 三类异常策略

类型 处理方式
业务异常 明确返回给用户
可恢复异常 重试/降级
不可恢复异常 快速失败

8.2 全局异常处理

推荐统一异常网关:

GlobalExceptionHandler
  ↓
日志记录
  ↓
统一响应

8.3 可观测性

异常处理必须配套:


九、反模式清单

以下都是常见的异常反模式:


十、总结:异常设计方法论

可以用一句话总结:

异常设计 = 复杂度管理

一个优秀的异常设计应该做到:

关联内容(自动生成)