Java中try-with-resources自动关闭资源的核心是资源类必须实现AutoCloseable接口,其close()方法声明可抛出Exception,支持各类需清理的资源;自定义类只需实现该接口并合理实现close()逻辑即可。

Java 中的 try-with-resources 能自动关闭资源,核心在于资源对象必须实现 AutoCloseable 接口。JVM 在 try 块执行结束(无论正常完成还是抛出异常)后,会自动调用该接口的 close() 方法,无需手动写 finally 块。
AutoCloseable 接口长什么样?
AutoCloseable 是一个函数式接口,只定义了一个 void 返回类型的 close() 方法:
public interface AutoCloseable {
void close() throws Exception;
}
注意:它的 close() 方法声明可抛出 Exception,比 Closeable(继承自 AutoCloseable,限定抛出 IOException)更宽泛,适合各类需要清理的资源(如数据库连接、线程池、自定义句柄等)。
怎么让自己的类支持 try-with-resources?
只需让类实现 AutoCloseable,并提供有意义的 close() 实现:
立即学习“Java免费学习笔记(深入)”;
- 释放底层持有的系统资源(如文件句柄、网络 socket、内存映射等)
- 清空或重置内部状态(比如标记为“已关闭”,防止重复使用)
- 避免在
close()中抛出未处理的运行时异常(否则可能掩盖主逻辑异常)
示例:
public class MyResource implements AutoCloseable {
private boolean closed = false;
@Override
public void close() {
if (!closed) {
System.out.println("释放自定义资源...");
closed = true;
}
}
}
使用时直接写在 try 后的括号里:
try (MyResource r = new MyResource()) {
// 使用 r
} // 自动调用 r.close()
多个资源怎么处理?顺序有讲究吗?
可以在 try 后声明多个资源,用分号分隔:
try (FileInputStream fis = new FileInputStream("a.txt");
FileOutputStream fos = new FileOutputStream("b.txt")) {
// 复制文件
}
关闭顺序是「**逆序**」:后声明的先关闭(即 fos 先于 fis 关闭)。这是为了满足依赖关系——比如流包装器(BufferedInputStream 包装 FileInputStream)必须先关外层,再关内层。
如果某个 close() 抛异常:
- 若 try 块中已有异常,该 close 异常会被抑制(suppressed),可通过
Throwable.getSuppressed()获取 - 若 try 块无异常,则第一个抛出的 close 异常成为最终异常
常见误区和注意事项
不是所有“带 close 方法”的类都能用 try-with-resources —— 必须显式实现 AutoCloseable 或其子接口(如 Closeable)。
-
java.sql.Connection、java.io.FileInputStream等标准类已实现,可直接用 - 不要在
close()中做耗时或阻塞操作(如等待线程结束),否则拖慢 try 块退出 - 不要在
close()中重新抛出被吞掉的异常(比如忽略IOException),否则资源泄漏风险上升 - 资源变量必须是 final 或“ effectively final”(不能在 try 块内重新赋值)


















