要获取被抑制的异常,需在 catch 中调用主异常的 getSuppressed() 方法,该方法返回 Throwable[] 数组,按资源逆序关闭顺序排列,索引 0 对应最后关闭资源的异常;数组为空表示无 suppressed 异常。

在 try-with-resources 中,如果 try 块抛出异常,同时资源的 close() 方法也抛出异常,Java 会将 close 异常作为 suppressed exception(被抑制异常)添加到主异常中,而不是覆盖或丢弃它。要获取这些被抑制的异常,需调用主异常对象的 getSuppressed() 方法。
如何获取被抑制的异常
主异常(即 try 块中抛出的异常)是实际被 throw 出去的那个,它的 getSuppressed() 方法返回一个 Throwable[] 数组,包含所有因 close 失败而被抑制的异常。
- 必须在捕获主异常后调用
getSuppressed(),不能对catch子句中的异常变量直接“再 catch” - 数组长度为 0 表示没有被抑制异常(例如:close 成功,或 try 块没抛异常)
- 每个被抑制异常本身也可能有自己的 suppressed,但标准资源关闭通常不会嵌套
一个典型示例
假设有两个资源,r1 在 try 块中抛出 IOException("read failed"),而 r2.close() 抛出 IOException("close failed"):
try (Resource r1 = new Resource();
Resource r2 = new Resource()) {
throw new IOException("read failed");
} catch (IOException e) {
System.out.println("Main exception: " + e.getMessage());
for (Throwable s : e.getSuppressed()) {
System.out.println("Suppressed: " + s.getMessage());
}
}
输出为:
立即学习“Java免费学习笔记(深入)”;
Main exception: read failedSuppressed: close failed
多个资源时的 suppressed 顺序
资源按声明**逆序**关闭(即后声明的先 close),因此被抑制异常的顺序与 close 失败的顺序一致,getSuppressed() 返回的数组索引 0 对应最后关闭的资源所抛出的异常(最晚发生的 close 异常)。
- 若声明顺序为
r1、r2、r3,则 close 顺序是r3 → r2 → r1 - 若三者 close 全失败,则
getSuppressed()[0]是r3.close()的异常,[1]是r2.close()的,依此类推
注意点与常见误区
不捕获 close 异常:不要在资源类的 close() 中 try-catch 并吞掉异常——这会导致 suppressed 丢失;应让异常自然抛出。
主异常为 null 不可能:try-with-resources 总会有一个主异常(要么 try 块抛出,要么某个 close 抛出且前面都成功——此时该 close 异常就是主异常,无 suppressed)。
自定义资源需实现 AutoCloseable:确保 close() 方法签名正确,并在出错时真实抛出异常,而非静默处理。


















