Skip to content

2026-08-27 · 程序出错时怎么处理——try-catch-finally、throws、自定义异常。

Java 异常处理

1. 异常是什么

程序运行时出错,Java 会抛出异常对象:

java
int[] arr = {1, 2, 3};
System.out.println(arr[5]); // ❌ ArrayIndexOutOfBoundsException

不处理异常,程序会崩溃(打印红色堆栈信息然后终止)。

2. try-catch-finally

捕获异常,让程序继续运行:

java
try {
    int[] arr = {1, 2, 3};
    System.out.println(arr[5]); // 可能出错的代码
} catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("数组越界:" + e.getMessage()); // 处理异常
} finally {
    System.out.println("无论是否出错都会执行"); // 可选
}
// 输出:
// 数组越界:Index 5 out of bounds for length 3
// 无论是否出错都会执行

catch 可以捕多种异常

java
try {
    // 可能出多种错
} catch (ArithmeticException e) {
    // 算术错误(除以零)
} catch (ArrayIndexOutOfBoundsException e) {
    // 数组越界
} catch (Exception e) {
    // 兜底:捕获所有其他异常
}

catch 从上到下匹配,命中第一个就停。兜底的 Exception 放最后。

try-with-resources(Java 7+)

java
// 自动关闭资源(文件、数据库连接等)
try (FileReader reader = new FileReader("test.txt")) {
    // 使用资源
    reader.read();
} // 自动调用 reader.close(),不用写 finally

涉及 IO/数据库操作时,用 try-with-resources 更安全(不会忘记关闭)。

3. throws 与 throw

throws(声明可能抛出的异常)

java
// 方法声明可能抛出什么异常
public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path); // 可能抛 IOException
    reader.read();
}

调用 throws 声明的方法时,必须处理异常(try-catch)或继续 throws。

throw(手动抛出异常)

java
public void setAge(int age) {
    if (age < 0 || age > 150) {
        throw new IllegalArgumentException("年龄不合法:" + age); // 手动抛出
    }
    this.age = age;
}

throws vs throw

区别throwsthrow
位置方法签名上方法体内
含义声明"这个方法可能抛异常"手动"抛出一个异常"
后面跟异常类名异常对象

4. 受检异常 vs 非受检异常

java
// 受检异常(Checked Exception):必须处理,编译器强制检查
try {
    FileReader reader = new FileReader("不存在.txt"); // 编译报错!必须 try-catch 或 throws
} catch (FileNotFoundException e) {
    // 处理
}

// 非受检异常(Unchecked Exception):运行时才报错,不强制处理
int[] arr = {1, 2, 3};
arr[5]; // 运行时才报 ArrayIndexOutOfBoundsException

常见异常分类

类型常见异常是否强制处理
受检异常IOException、FileNotFoundException、SQLException✅ 必须
非受检异常NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException❌ 不强制
错误(Error)OutOfMemoryError、StackOverflowError❌ 不处理(JVM 级别)

日常开发中,受检异常用 try-catch 或 throws;非受检异常靠代码逻辑避免(判空、边界检查)。

5. 常见异常速查

java
NullPointerException       // 空指针:对 null 调方法
ArrayIndexOutOfBoundsException // 数组越界
ClassCastException          // 类型转换失败
NumberFormatException       // 字符串转数字失败(Integer.parseInt("abc"))
IllegalArgumentException    // 非法参数(手动抛出)
FileNotFoundException       // 文件不存在

遇到异常先看异常类名,它会告诉你出了什么问题

6. 自定义异常

业务异常需要自己定义:

java
// 自定义受检异常
public class BusinessException extends Exception {
    private int code;

    public BusinessException(int code, String message) {
        super(message);
        this.code = code;
    }

    public int getCode() { return code; }
}

// 自定义非受检异常(更常用)
public class BusinessException extends RuntimeException {
    private int code;

    public BusinessException(int code, String message) {
        super(message);
        this.code = code;
    }

    public int getCode() { return code; }
}

// 使用
public void save(User user) {
    if (user.getName() == null) {
        throw new BusinessException(1001, "用户名不能为空");
    }
}

Spring Boot 项目里通常继承 RuntimeException(非受检),配合全局异常处理器 @RestControllerAdvice 统一返回错误信息。等学 Spring 再深入。