try-with-resources通过在try括号内声明AutoCloseable资源实现自动关闭,替代易错的手动finally关闭;多资源按声明逆序关闭,close异常被抑制而不掩盖主异常。

Java 传统 try-catch-finally 中手动关闭资源(如 InputStream、Connection)容易出错,而 try-with-resources 能自动关闭实现了 AutoCloseable 接口的资源,更简洁安全。改写核心是:把资源声明移到 try 括号内,移除 finally 块和显式 close() 调用。
资源必须实现 AutoCloseable 接口
只有实现了 java.lang.AutoCloseable(或其子接口 java.io.Closeable)的类才能用于 try-with-resources。常见如:
-
FileInputStream/BufferedReader -
Connection、PreparedStatement、ResultSet(JDBC 4.0+) -
Scanner、ZipInputStream
若自定义类需支持,只需在类声明中 implements AutoCloseable 并重写 close() 方法即可。
基本改写步骤
以读取文件为例,对比传统写法与改写后写法:
立即学习“Java免费学习笔记(深入)”;
传统写法(易漏 close 或异常覆盖):
InputStream is = null;
try {
is = new FileInputStream("data.txt");
// 处理数据
} catch (IOException e) {
// 处理异常
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// 关闭异常被吞或需额外处理
}
}
}
改写为 try-with-resources:
try (InputStream is = new FileInputStream("data.txt")) {
// 处理数据(is 在此作用域内可用)
} catch (IOException e) {
// 处理业务异常(close() 异常会自动抑制,不打断主异常)
}
注意:is 在 try 括号中声明,自动在 try 块结束时调用 close(),无需 finally,也不用判空。
多个资源的声明与关闭顺序
多个资源用分号隔开,按声明**逆序**关闭(后声明的先关闭),适合有依赖关系的场景(如先关 ResultSet,再关 Statement,最后关 Connection):
try (Connection conn = DriverManager.getConnection(url);
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
// 处理结果
}
} catch (SQLException e) {
// 统一捕获所有可能的 SQL 异常
}
这里 rs 最先关闭,然后是 ps,最后是 conn —— 符合 JDBC 资源释放规范。
异常处理细节: suppressed 异常
如果 try 块抛出异常,且 close() 也抛出异常,后者会被“抑制(suppressed)”,不会覆盖主异常,但可通过 Throwable.getSuppressed() 获取:
try (Resource r = new Resource()) {
r.doSomething(); // 抛出 IOException
} catch (IOException e) {
// e 是主异常;若 r.close() 也抛异常,它被 suppress 并附加到 e 上
for (Throwable suppressed : e.getSuppressed()) {
System.err.println("Suppressed: " + suppressed);
}
}
这种机制确保关键业务异常不被关闭逻辑掩盖,同时不丢失关闭失败的信息。


















