异常体系与资源管理总览
学习目标
- 区分 Error、checked exception 和 RuntimeException 的责任边界。
- 知道 throw、throws、try-with-resources 与 suppressed exception 分别解决什么问题。
- 能跳转到异常处理和自定义异常页面,按场景复制代码。
核心知识点
专业术语
- Throwable:Error 与 Exception 的共同根类型。
- checked exception:编译器要求捕获或声明的 Exception 分支。
- unchecked exception:RuntimeException 及 Error 分支,不要求在签名中声明。
- try-with-resources:自动调用 AutoCloseable.close() 的资源管理语句。
- suppressed exception:主异常发生后,资源关闭等辅助失败被附加保存的异常。
白话解释与边界
Error 通常表示虚拟机或运行环境级严重问题,不应被业务 catch 统一吞掉;RuntimeException 常表示输入、状态或编程错误;checked exception 适合调用方有明确恢复路线的外部失败。异常处理的重点不是“捕获越多越好”,而是让知道如何恢复的层负责恢复。
详细案例已拆分:
- 异常处理常用写法:try-catch、throw、throws、finally、try-with-resources。
- 自定义异常与异常转换:领域异常、cause、异常翻译和 suppressed。
常用用法
按异常责任选择捕获或传播
当前层能给出安全默认值时才恢复;没有恢复策略时应保留上下文继续传播。
java
// 语义:当前层能给出安全默认值时才恢复。
public class ExceptionBoundaryOverviewDemo {
static int parse(String value) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException error) {
return 0;
}
}
public static void main(String[] args) {
System.out.println(parse("bad"));
// 输出:0
}
}用 try-with-resources 关闭资源
资源按声明逆序关闭;完整的多资源、finally 和关闭异常案例见异常处理常用写法。
java
// 语义:资源按声明逆序关闭。
import java.io.StringReader;
import java.io.BufferedReader;
import java.io.IOException;
public class ResourceOverviewDemo {
public static void main(String[] args) throws IOException {
try (BufferedReader reader =
new BufferedReader(new StringReader("java"))) {
// 初始状态:new StringReader("java") 提供一行文本,BufferedReader reader 包装该字符流并在 try 结束时自动关闭。
System.out.println(reader.readLine());
// 输出:java
}
}
}用 cause 保留底层异常
异常转换时补充当前层语境,但不要丢掉 cause;领域异常的构造器和结构化字段见自定义异常页面。
java
// 语义:异常转换时补充当前层语境,但不要丢掉 cause。
// 初始状态:root 初始为 new IllegalStateException("db down");translated 初始为 new RuntimeException("load failed", root)。
public class CauseOverviewDemo {
public static void main(String[] args) {
IllegalStateException root = new IllegalStateException("db down");
// 关键变化:root 接收表达式 new IllegalStateException("db down") 的计算结果。
// 初始状态:root 的初始值为 new IllegalStateException("db down")。
RuntimeException translated = new RuntimeException("load failed", root);
// 初始状态:translated.message 为 "load failed",cause 指向 message="db down" 的 root。
System.out.println(translated.getCause().getMessage());
// 输出:db down
}
}不常用但需要知道
读取 suppressed exception
suppressed 用于保留主异常之外的关闭或审计失败;日志排查资源问题时不能只看主异常消息。
java
public class SuppressedOverviewDemo {
public static void main(String[] args) {
IllegalStateException main = new IllegalStateException("body");
// 关键变化:main 接收表达式 new IllegalStateException("body") 的计算结果。
// 初始状态:main 的初始值为 new IllegalStateException("body")。
main.addSuppressed(new IllegalStateException("close"));
// 关键变化:main.addSuppressed(...) 把 message="close" 的异常加入 suppressed 数组第 0 项。
System.out.println(main.getSuppressed()[0].getMessage());
// 输出:close
}
}识别 finally return 的覆盖风险
finally 中 return 会覆盖原返回值和异常,新代码只在 finally 做清理,不改变控制流。
java
public class FinallyOverviewDemo {
static int value() {
try {
return 1;
} finally {
return 2;
}
}
public static void main(String[] args) {
System.out.println(value());
// 输出:2
}
}简单案例
java
public class ExceptionOverviewDemo {
static int parse(String value) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException error) {
return 0;
}
}
public static void main(String[] args) {
System.out.println(parse("bad"));
// 输出:0
}
}简单输入错误在当前层可以恢复;资源关闭、异常链和自定义异常分别见两个细粒度页面。
易混点
- throw 是抛出对象,throws 是方法声明;后者不会自动处理异常。
- catch Exception 不是通用恢复方案,Error 通常不应被业务代码捕获。
- try-with-resources 的关闭异常通常进入 suppressed,不会简单覆盖主体异常。
- finally 中 return 会掩盖原异常,资源清理应使用无返回值的 finally 或 try-with-resources。
课后小问
为什么资源关闭异常需要放到 suppressed? 答案:主体异常已经说明主要故障,关闭异常作为辅助诊断信息附加保存。 解析:同时保留两类异常可以避免资源释放失败被吞掉,也避免它覆盖调用方更关心的主体异常。
异常体系总览页和细粒度页面如何配合? 答案:先用本页判断责任边界,再按需要打开异常处理常用写法或自定义异常页面复制案例。 解析:总览页负责术语和选择,细节页把每个 API 作为独立小标题,适合直接检索。
本节小结
- Throwable 层次帮助划分恢复、传播和严重故障边界。
- try-with-resources 管理资源生命周期,suppressed 保存辅助关闭故障。
- 异常翻译必须保留 cause,finally 不应改变控制流。
- 具体代码按场景拆到两个关联页面,原 URL 继续作为入口保留。
快速回顾
- 能区分 checked、unchecked 和 Error。
- 能解释 throw、throws、finally 的职责。
- 能说出资源关闭顺序和 suppressed 的来源。
- 能从本页跳转到对应的异常速查页面。
阿源的知识库