Java的异常处理机制是确保程序健壮性和可靠性的关键部分。以下从异常分类、处理方式、区别及应用场景等方面进行详细说明:
一、异常分类
Java异常分为两大类:Checked Exception(受检异常) 和 Unchecked Exception(非受检异常),后者包含 RuntimeException 及其子类,以及 Error 及其子类。
| 类型 | 特点 | 常见示例 |
|---|---|---|
| Checked Exception | 编译时强制检查,必须捕获或声明抛出 | IOException, SQLException, ClassNotFoundException |
| RuntimeException | 运行时异常,不强制处理,通常由程序逻辑错误引起 | NullPointerException, IndexOutOfBoundsException, IllegalArgumentException |
| Error | 严重系统级错误,程序通常无法恢复 | OutOfMemoryError, StackOverflowError, NoClassDefFoundError |
二、异常处理方式
1. try-catch-finally
- 语法:
try { // 可能抛出异常的代码 } catch (ExceptionType1 e1) { // 处理ExceptionType1 } catch (ExceptionType2 e2) { // 处理ExceptionType2 } finally { // 无论是否异常,最终执行的代码(如释放资源) } - 作用:捕获并处理异常,
finally块确保资源释放。 - 注意:
- 多个
catch块时,子类异常在前,父类在后。 - Java 7+支持多异常捕获:
catch (IOException | SQLException e)。
- 多个
2. throw
- 语法:
throw new ExceptionType("message"); - 作用:在方法内部主动抛出异常,通常用于传递错误。
3. throws
- 语法:
public void method() throws IOException, SQLException { ... } - 作用:声明方法可能抛出的异常,强制调用者处理(针对Checked Exception)。
4. try-with-resources
- 语法(Java 7+):
try (ResourceType res = new ResourceType()) { // 使用资源 } catch (Exception e) { // 处理异常 } - 作用:自动关闭实现
AutoCloseable的资源(如文件流、数据库连接),避免资源泄漏。
5. 自定义异常
- 实现:继承
Exception(Checked)或RuntimeException(Unchecked)。 - 示例:
public class InvalidInputException extends RuntimeException { public InvalidInputException(String message) { super(message); } }
三、Checked vs. Unchecked 异常的区别
| 对比维度 | Checked Exception | Unchecked Exception |
|---|---|---|
| 处理强制 | 必须捕获或声明抛出 | 不强制处理 |
| 来源 | 外部不可控因素(如I/O、网络) | 程序逻辑错误(如空指针、参数不合法) |
| 恢复可能性 | 通常可恢复 | 通常不可恢复,需修复代码 |
| 设计意图 | 提醒调用者处理已知风险 | 提示开发者修复程序缺陷 |
四、应用场景
1. Checked Exception
- 场景:预期可能发生且需程序显式处理的异常。
- 示例:
- 文件操作(
FileNotFoundException)。 - 数据库访问失败(
SQLException)。
- 文件操作(
- 代码示例:
public void readFile() throws IOException { try (FileReader fr = new FileReader("file.txt")) { // 读取文件 } }
2. Unchecked Exception
- 场景:程序逻辑错误或不可恢复的系统错误。
- 示例:
- 参数校验失败(
IllegalArgumentException)。 - 数组越界(
IndexOutOfBoundsException)。
- 参数校验失败(
- 代码示例:
public void setAge(int age) { if (age < 0) { throw new IllegalArgumentException("年龄不能为负数"); } this.age = age; }
3. 自定义异常
- 场景:业务规则相关的错误,需明确错误语义。
- 示例:
- 用户输入格式错误(
InvalidInputException)。 - 订单状态冲突(
OrderStateException)。
- 用户输入格式错误(
- 代码示例:
public void placeOrder(Order order) { if (order == null) { throw new InvalidInputException("订单不能为空"); } // 处理订单逻辑 }
五、最佳实践
- 避免空catch块:至少记录异常(如
e.printStackTrace())或恢复操作。 - 精准捕获异常:避免直接捕获
Throwable或Exception,优先捕获具体异常。 - 异常链传递:包装底层异常,保留原始信息:
throw new CustomException("操作失败", e); - 慎用Checked Exception:避免过度使用导致代码冗余(如Spring提倡Unchecked异常)。
- 性能优化:异常处理较慢,高频场景用条件判断替代(如
if (obj != null)而非捕获NullPointerException)。
六、总结
- Checked异常:用于可预见的、需调用者处理的错误(如外部依赖失败)。
- Unchecked异常:用于程序内部错误,提示开发者修复代码。
- 自定义异常:增强业务逻辑的可读性和可维护性。
- 资源管理:优先使用
try-with-resources,避免资源泄漏。

7303

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



