try-with-resources 的原理是什么?异常抑制如何处理?

结论先行:try-with-resources 是 JDK 7 引入的语法糖:声明在 try 括号中的资源(实现 AutoCloseable)在块结束时按声明逆序自动 close;若 close 抛异常且主逻辑也抛了异常,close 的异常会被追加为抑制异常(suppressed),绝不覆盖主异常。它替代了 finally + close 的样板代码,是资源管理的推荐写法。

关键规则

规则说明
资源类型必须实现 AutoCloseable(Closeable 是其子接口)
关闭顺序后声明的先关闭(逆序)
主异常优先块内异常 + close 异常同时出现时,close 异常被抑制
读取抑制异常Throwable.getSuppressed() 可取回被抑制的异常
多资源写法括号内用分号声明多个,无需嵌套
import java.io.*;

public class TwrDemo {
    static void copy(String src, String dst) throws IOException {
        // 两个资源自动关闭,且 out 先于 in 关闭
        try (InputStream in = new FileInputStream(src);
             OutputStream out = new FileOutputStream(dst)) {
            byte[] buf = new byte[1024];
            int n;
            while ((n = in.read(buf)) != -1) {
                out.write(buf, 0, n);
            }
        }
    }

    public static void main(String[] args) throws Exception {
        try (AutoCloseable a = () -> { throw new RuntimeException("close失败"); }) {
            throw new IllegalStateException("主异常");
        } catch (Exception e) {
            System.out.println("主异常: " + e);
            for (Throwable s : e.getSuppressed()) { // 查看被抑制的异常
                System.out.println("被抑制: " + s);
            }
        }
    }
}

常见追问 / 记忆点

  • 记忆点:资源要 AutoCloseable、关闭按逆序、close 异常让位给主异常成为 suppressed。
  • 追问:编译后 try-with-resources 会被展开成 try/finally,并用 addSuppressed 挂载 close 异常。
  • 追问:不止流能关——Connection/Statement、锁等实现 AutoCloseable 的对象都适用;JDK 9 起 final 或等效 final 的变量也可作为资源。
笔记加载中…