try-with-resources 的资源按声明逆序关闭,自动调用 close() 且支持异常抑制;资源须实现 autocloseable,构造失败者不被关闭,嵌套资源可显式统一管理。

Java 中 try-with-resources 的“隐式 finally”并不是真正独立的 finally 块,而是编译器在生成字节码时,自动将资源的 close() 调用插入到 try 语句结束后的清理位置(类似 finally 的语义),且对多个资源按**声明逆序**自动调用 close() —— 这是关键,无需手动写 finally。
资源按声明逆序关闭
try-with-resources 中,资源在小括号内以分号分隔,编译器会从右到左依次调用每个资源的 close() 方法。这符合“后创建、先释放”的原则,避免依赖关系导致的异常或状态错误。
-
例如:
try (A a = new A(); B b = new B(); C c = new C()) { ... }→ 关闭顺序是c.close()→b.close()→a.close() - 即使某个
close()抛出异常,后续资源仍会继续关闭(除非发生严重错误如 JVM 退出)
异常抑制机制保障多资源清理
如果 try 块中已抛出异常,而某个 close() 又抛出新异常,后者不会覆盖主异常,而是被“抑制(suppressed)”,可通过 Throwable.getSuppressed() 获取。这样既保证主异常不丢失,又确保所有资源都尝试释放。
- 主异常(try 块中抛出的)始终是最终抛出的那个
- 被抑制的异常不会中断关闭流程 —— 其他资源仍会继续调用
close() - 所有资源无论是否抛异常,都会执行
close()(只要其引用非 null)
资源必须实现 AutoCloseable
只有实现了 AutoCloseable(或其子接口 Closeable)的类才能用于 try-with-resources。编译器据此生成调用逻辑;否则编译不通过。
- 自定义资源只需重写
close()方法,做好自身清理(如释放文件句柄、网络连接、数据库连接等) - 注意:
close()应幂等 —— 多次调用不应报错或产生副作用 - 若资源构造失败(如构造器抛异常),未成功赋值的变量不会被 close(因为其引用为 null)
嵌套资源也可统一管理
多个资源可以是相互关联的(如 FileInputStream 包含底层文件句柄,BufferedInputStream 包装它),只要都声明在 try 括号内,就会各自独立 close —— 不需要靠外层资源的 close 来触发内层释放。
- 推荐显式声明所有需管理的资源,而非依赖包装类的级联关闭
- 例如:
try (FileInputStream fis = new FileInputStream(...); BufferedInputStream bis = new BufferedInputStream(fis))→bis.close()和fis.close()都会被调用(除非bis.close()已关闭底层流且不再允许重复关闭) - 实际中更常见的是只声明最外层包装流(如
BufferedInputStream),因其close()通常会委托给底层流;但显式声明两者更明确、更安全
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











