在 Java 中,捕获(Catch) 和 抛出(Throw) 是异常处理的两个核心操作,它们的用途和行为有本质区别:
1. 捕获异常(Catch)
作用
在 try-catch 块中 捕获并处理异常,防止程序因异常中断。
特点
- 使用
try-catch代码块。 - 异常被捕获后,程序会继续执行
catch块或后续代码。 - 适合处理已知可恢复的错误。
示例
try {
int result = 10 / 0; // 抛出 ArithmeticException
} catch (ArithmeticException e) {
System.out.println("捕获到异常: " + e.getMessage()); // 处理异常
}
System.out.println("程序继续执行"); // 会执行
适用场景
- 文件读取失败后重试。
- 网络请求超时后降级返回默认值。
- 用户输入校验失败后提示重新输入。
2. 抛出异常(Throw)
作用
主动 抛出异常(向上传递或自定义异常),由调用者处理。
特点
- 使用
throw关键字或方法声明throws。 - 异常抛出后,当前方法停止执行,异常会向调用栈上层传递。
- 适合处理无法直接处理的错误。
示例
(1) 抛出内置异常
void validateAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负数"); // 主动抛出异常
}
}
(2) 声明方法可能抛出异常(throws)
void readFile() throws IOException { // 声明可能抛出IOException
Files.readString(Path.of("test.txt"));
}
适用场景
- 参数校验失败时中断流程。
- 底层方法遇到错误但无法处理(如数据库连接失败)。
- 自定义业务异常(如
UserNotFoundException)。
3. 核心区别
| 特性 | 捕获(Catch) | 抛出(Throw) |
|---|---|---|
| 关键字 | try-catch | throw 或 throws |
| 行为 | 处理异常,程序继续执行 | 中断当前方法,异常向上传递 |
| 责任方 | 当前方法处理异常 | 调用者处理异常 |
| 典型场景 | 可恢复的错误(如重试、降级) | 不可恢复的错误(如参数非法、资源缺失) |
4. 组合使用场景
(1) 捕获后重新抛出
捕获异常后,包装成自定义异常再抛出(常用于业务层):
try {
paymentService.process();
} catch (IOException e) {
throw new PaymentFailedException("支付失败", e); // 包装原始异常
}
(2) 选择性处理
部分异常捕获处理,其余抛出:
void loadConfig() throws FileNotFoundException {
try {
File file = new File("config.json");
FileReader reader = new FileReader(file);
} catch (SecurityException e) {
System.out.println("无权限访问文件"); // 处理SecurityException
}
// FileNotFoundException 会继续抛出
}
5. 常见误区
-
过度捕获异常:
- 反例:捕获
Exception后什么都不做(隐藏问题)。 - 正确做法:只捕获能处理的异常,其余抛出。
- 反例:捕获
-
滥用抛出异常:
- 反例:用异常替代条件判断(如
if (obj == null)写成throw new NullPointerException())。 - 正确做法:异常应用于意外错误,而非正常逻辑分支。
- 反例:用异常替代条件判断(如
-
忽略异常链:
- 反例:
throw new MyException("error")(丢失原始异常信息)。 - 正确做法:
throw new MyException("error", e)保留原始异常。
- 反例:
6. 总结
- 捕获异常:解决当前能处理的错误,保证程序继续运行。
- 抛出异常:将错误传递给上层,由合适的调用者处理。
- 设计原则:
- 底层方法(如工具类)优先抛出异常。
- 上层业务代码(如Controller)优先捕获异常并转换为用户友好提示。
通过合理使用捕获和抛出,可以构建健壮且易维护的异常处理体系。
1506

被折叠的 条评论
为什么被折叠?



