Java try-with-resources

try-with-resources 如何在异常路径上可靠关闭资源,以及抑制异常(suppressed)语义。

#type / concept #status / growing #tech / dev #resource / java

[!info] 关联笔记

Java try-with-resources

这个概念为什么出现

文件、套接字、数据库连接都必须关闭。手工 try/finally 易漏、顺序错、二次异常掩盖主异常。try-with-resources 把“用完即关”做成语法,并保留抑制异常信息。

[!abstract] 一句话理解 在 try (...) 中声明的 AutoCloseable 资源会在块结束时按逆序自动 close;主异常上可挂载关闭阶段的 suppressed 异常。

最小可运行示例

场景:导出服务写临时报表文件

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;

public class ReportExport {
    // export:写一行报表。
    // 教学点:BufferedWriter 在 try-with-resources 中自动关闭(会 flush)。
    static void export(Path path, String line) throws IOException {
        try (BufferedWriter w = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
            w.write(line);
            w.newLine();
        } // 此处自动 close
    }

    public static void main(String[] args) throws Exception {
        Path p = Files.createTempFile("report-", ".txt");
        export(p, "order=1,ok");
        System.out.println(Files.readString(p).trim());
        Files.deleteIfExists(p);
    }
}

建议运行:

javac ReportExport.java && java ReportExport

期望输出:

order=1,ok

结合场景再看三个关注点

  1. 资源声明在 try 括号内才自动管理。
  2. 多个资源逆序关闭(后开先关)。
  3. 关闭失败不会默默丢掉主异常(suppressed)。

核心概念与准确模型

1. 语法

try (Resource r = open()) {
  use(r);
}

2. 等价直觉

编译器生成 finally 风格关闭,并处理异常抑制。

3. 抑制异常

  • 主异常在 body
  • close 抛出的额外异常进入 getSuppressed()

4. 生效条件

  • 资源实现 AutoCloseable/Closeable
  • 变量有效 final

边界情况与反直觉行为

  1. 资源赋值 null 不会 close。
  2. 在 body 里手动提前 close 要避免双重语义混乱。
  3. 依赖关闭顺序的资源要按正确顺序声明。

常见误区

[!warning] 常见误区:打开资源在 try 外再在 finally close 新代码优先 try-with-resources,减少遗漏。

工程实践

  1. IO/JDBC/HTTP 客户端响应体一律 TWR。
  2. 自定义资源实现 AutoCloseable
  3. 测试异常路径是否仍关闭(可用计数包装)。
  4. 日志打印 suppressed。

本节总结

  • 自动关闭 + 异常更安全
  • 逆序 close + suppressed
  • IO/JDBC 标配

自测题

  1. 两个资源关闭顺序?
  2. 为什么还需要 getSuppressed
参考答案
  1. 与声明相反:后获取的先关闭。
  2. 关闭阶段异常不能覆盖主异常,但必须可观测。

延伸阅读与资料来源

资料类型支撑内容
The try-with-resources Statement教程语法与 suppressed
AutoCloseableAPI关闭契约
创建于 2026/7/15 更新于 2026/7/15