版本:基于 Java 17 & Java 21 LTS

在编写代码的过程中,错误是不可避免的。Java 的异常处理机制为我们提供了一种优雅的方式来捕获和处理这些错误,而不是让程序直接崩溃。本篇将介绍现代 Java 中处理异常的最佳实践。


1. 异常的体系结构

Java 中的异常都是 Throwable 类的子类。

  • Error:严重错误,通常由 JVM 触发(如 OutOfMemoryError)。

  • Exception:程序可以处理的错误。

    • 编译时异常 (Checked Exception):强制要求处理。

    • 运行时异常 (Runtime Exception):通常由逻辑错误引起(如 NullPointerException)。


2. 基础捕获:try-catch-finally

这是最基础的捕获机制:

try {
    var result = 10 / 0;
} catch (ArithmeticException e) {
    System.err.println("除零错误: " + e.getMessage());
} finally {
    System.out.println("清理工作:无论是否发生异常,我都会执行。");
}

3. 资源管理:Try-with-resources (Java 7+)

这是现代 Java 处理资源(如文件、数据库连接)的标准方式

import java.io.*;

public class ResourceTest {
    public static void main(String[] args) {
        // 资源在括号内声明,会在 try 结束时自动关闭
        try (var reader = new BufferedReader(new FileReader("test.txt"))) {
            System.out.println(reader.readLine());
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }
}

4. 异常链与自定义异常

4.1 异常链 (Exception Chaining)

当捕获到一个异常并抛出另一个新异常时,应保留原始异常信息,这被称为“异常链”。

try {
    // 数据库操作
} catch (SQLException e) {
    // 将 SQL 异常包装成业务异常,并传递原始异常 e
    throw new BusinessException("保存失败", e);
}

4.2 自定义异常最佳实践

继承 RuntimeException 通常更符合现代框架(如 Spring)的习惯。

public class UserNotFoundException extends RuntimeException {
    public UserNotFoundException(String message) {
        super(message);
    }
}

5. 异常处理的原则

  1. 只捕获你能处理的异常:不要盲目使用 catch (Exception e)

  2. 不要在 finally 中写 return:这会吞掉 try 块中的返回值或异常。

  3. 尽早抛出,延迟捕获:在最接近错误源的地方抛出异常,在能够处理它的层级进行捕获。


本章小结

第七篇我们深度学习了:

  1. Java 异常体系的基本分类。

  2. Try-with-resources:现代资源管理的终极方案。

  3. 异常链:保留错误上下文的技巧。

  4. 如何根据业务需求创建自定义异常及其实战原则。

下一篇预告:泛型进阶与函数式编程 (Generics, Lambda, Functional Interfaces)