必须实现AutoCloseable接口才能用于try-with-resources;资源按声明逆序关闭,需注意依赖关系;close()异常会被抑制,可通过getSuppressed()获取;自定义类需显式实现接口并正确重写close()方法。
直接用 try-with-resources 语法,前提是资源类实现了 autocloseable 接口。jvm 会在 try 块结束时(无论是否抛异常)自动调用每个资源的 close() 方法,无需手动写 finally 或重复关闭逻辑。
资源声明必须满足 AutoCloseable 约束
不是有 close() 方法就能进 try-with-resources —— 编译器只认接口契约:
- 类必须显式
implements AutoCloseable(或其子接口如Closeable) -
close()方法签名必须匹配:返回 void,可声明throws Exception(若只抛IOException,用Closeable更准确) - 像
FileInputStream、BufferedReader、Connection、ResultSet都已实现,可直接用;自己写的工具类哪怕有 public void close(),没实现接口就编译报错
多个资源要按依赖顺序声明
多个资源用分号隔开,关闭顺序是声明的逆序,这点直接影响正确性:
- 正确示例:
try (Connection c = ds.getConnection(); PreparedStatement ps = c.prepareStatement(sql)) { ... }→ 先关ps,再关c,符合依赖关系 - 错误写法:
PreparedStatement ps = ...; Connection c = ...→ 会先关c,再关ps,执行ps.close()时可能报 “connection closed” - 注意:不能在括号里写
MyResource r = new MyResource()这类带变量名赋值的完整语句,只能是类型 变量名 = 表达式形式
异常处理机制需特别留意
try-with-resources 内部已集成异常抑制逻辑,不用额外捕获 close 异常:
- 如果 try 块抛异常,且某个
close()也抛异常,后者会被“抑制”,主异常仍被抛出 - 可通过
exception.getSuppressed()获取被抑制的异常列表 - 所有资源都会尝试关闭,即使前面的
close()抛了异常,后面的仍会继续调用(不像传统 finally 中一个失败就中断后续)
自定义资源类的实操要点
想让自己的类支持 try-with-resources,三步到位:
- 声明实现
AutoCloseable:public class MyResource implements AutoCloseable - 重写
close()方法,做清理工作(如释放锁、断开连接、清空缓存),并声明throws Exception - 避免在
close()中抛出未检查异常(如NullPointerException),否则可能掩盖真实问题;若必须,应提前判空或记录日志

















