在try-with-resources中,若try块和资源关闭均抛异常,后者被抑制并附加到主异常,需调用getSuppressed()获取;其返回数组长度可能为0,异常顺序与声明顺序相反。

在 try-with-resources 中,如果 try 块抛出异常,同时资源关闭过程中也抛出异常,后者会被“抑制”(suppressed),并附加到主异常上。要获取被抑制的异常信息,需调用主异常的 getSuppressed() 方法。
检查是否有被抑制的异常
并非所有异常都有被抑制的异常——只有 try 块本身抛出异常,且至少一个资源的 close() 方法也抛出异常时,才会发生抑制。因此,应先确认主异常是否为实际抛出的那个(比如 catch 中捕获的),再调用 getSuppressed():
- 该方法返回
Throwable[],长度可能为 0(无抑制异常) - 即使有多个资源,也只会在主异常上添加关闭阶段抛出的异常,不会叠加到彼此上
- 抑制异常的顺序与资源声明顺序相反(后声明的资源先关闭,其异常先被抑制)
遍历并打印被抑制的异常
可在 catch 块中遍历 getSuppressed() 结果,输出堆栈或关键信息:
try (FileInputStream fis = new FileInputStream("a.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(fis))) {
reader.readLine();
} catch (IOException e) {
System.err.println("主异常: " + e.getMessage());
for (Throwable suppressed : e.getSuppressed()) {
System.err.println("被抑制异常: " + suppressed);
suppressed.printStackTrace(System.err); // 可选:打印完整堆栈
}
}
自定义异常处理逻辑
若需聚合或筛选抑制异常,可结合判断类型、消息内容等:
立即学习“Java免费学习笔记(深入)”;
- 用
suppressed instanceof SQLException区分异常类型 - 对重要抑制异常重新抛出(如关闭数据库连接失败),但需注意避免覆盖主异常语义
- 记录日志时建议同时输出主异常和所有抑制异常的类名与消息,便于排查资源清理问题
注意 close() 方法本身的异常处理
资源类的 close() 方法应尽量避免抛出异常;若无法避免,应确保它不会掩盖业务逻辑的关键错误:
- 常见 JDK 类(如
BufferedWriter、ZipInputStream)的close()可能抛出 IOException - 自定义资源类中,可在
close()内部捕获并记录异常,而非向上抛出,从而避免抑制 - 若必须抛出,建议在文档中说明该异常的语义(例如“仅表示缓存刷新失败,不影响数据正确性”)


















