Java 异常处理全攻略:从分类、捕获到自定义异常
异常是程序运行时出现的异常事件,打断正常流程。Java 通过异常处理机制(try-catch-finally、throws、try-with-resources)实现健壮的错误控制。
异常三大类别
| 类别 | 特点 | 典型示例 |
|---|---|---|
| 受检异常 | 编译期检查,必须捕获或声明抛出 | IOException、FileNotFoundException、SQLException |
| 非受检异常 | 运行时抛出,编译器不强制处理 | NullPointerException、ArrayIndexOutOfBoundsException、IllegalArgumentException |
| 错误 | JVM 层面严重问题,通常无法恢复 | OutOfMemoryError、StackOverflowError |
异常继承体系
Throwable
├── Error // 严重错误,不处理
└── Exception // 程序可处理的异常
├── RuntimeException // 非受检异常父类
│ ├── NullPointerException
│ └── ...
├── IOException // 受检异常代表
└── ... // 其他受检异常
Throwable 核心方法
| 方法 | 用途 |
|---|---|
getMessage() | 获取异常详细信息 |
getCause() | 获取根因异常 |
toString() | 类名 + 信息 |
printStackTrace() | 打印堆栈轨迹到标准错误流 |
getStackTrace() | 获取堆栈元素数组(可程序化分析) |
捕获异常:try-catch-finally
try {
// 可能抛出异常的代码
} catch (ExceptionType1 e1) {
// 处理 ExceptionType1
} catch (ExceptionType2 e2) {
// 处理 ExceptionType2
} finally {
// 无论是否异常都执行,用于资源清理
}
规则:catch 顺序按子类到父类;finally 无异常也执行;try 必须配 catch 或 finally。
多异常捕获(Java 7+)
catch (IOException | FileNotFoundException ex) {
logger.log(ex);
throw ex;
}
throws 与 throw
- throws:方法签名声明抛出受检异常,推迟处理责任
- throw:显式抛出异常实例
public void readFile(String path) throws IOException {
if (path == null) throw new IllegalArgumentException("路径不能为空");
// ...
}
try-with-resources(Java 7+)
自动资源管理,实现 AutoCloseable 的资源在块结束时自动关闭,顺序与声明相反。
// 传统方式
FileReader fr = null;
try {
fr = new FileReader("file.txt");
// 读取...
} finally {
if (fr != null) try { fr.close(); } catch (IOException ignored) {}
}
// try-with-resources 方式(推荐)
try (FileReader fr = new FileReader("file.txt")) {
// 读取...
} // 自动调用 fr.close()
可声明多资源:try (Resource r1 = ...; Resource r2 = ...) { ... }
自定义异常
- 受检异常:继承
Exception - 非受检异常:继承
RuntimeException
// 受检异常示例:余额不足
public class InsufficientFundsException extends Exception {
private double amount;
public InsufficientFundsException(double amount) { this.amount = amount; }
public double getAmount() { return amount; }
}
// 使用
public void withdraw(double amt) throws InsufficientFundsException {
if (amt > balance) throw new InsufficientFundsException(amt - balance);
balance -= amt;
}
常见异常分类
- JVM 抛出:
NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException - 程序显式抛出:
IllegalArgumentException、IllegalStateException
最佳实践
- 捕获具体异常,避免
catch (Exception e)吞噬错误 - 异常链保留根因:
throw new MyException("原因", cause) - 资源释放放在 finally 或用 try-with-resources
- 文档化方法抛出的异常(
@throwsJavadoc) - 避免用异常控制业务流程,性能差且可读性低
java
- 精通 Java 运算符:类型、语法与实战示例
- Java 注释:类型、用法与最佳实践
- 精通 Java 增强 for 循环:语法、示例与最佳实践
- 精通 Java 字符串:创建、方法与最佳实践
- 精通 Java 接口:概念、实现与最佳实践
- 精通 Java 匿名内部类:定义、语法与实战示例
- 精通 Java 异常处理:try-catch、finally、throw 与 throws 详解
- Java throw 与 throws 深度解析:异常处理实战指南
- 精通 Java 多异常捕获:单 catch 块处理多异常
- 精通 Java Try-With-Resources:自动资源管理详解
- Java 注解详解:类型、放置位置与实战示例
- Java 断言实战指南:尽早发现 Bug 与保障代码可靠性