try-with-resources要求资源实现autocloseable接口,关闭按声明逆序执行,禁止手动close与自动关闭混用,异常抑制需主动检查。

资源必须实现 AutoCloseable 接口
只有实现了 AutoCloseable(或其子接口 Closeable)的类才能用于 try-with-resources。常见如 FileInputStream、BufferedReader、Connection、ResultSet 等,都已合规;但自定义工具类若未显式实现该接口,编译会直接报错:"cannot be auto-closed"。
注意:某些包装流(如 BufferedInputStream)只是代理,是否真正释放底层资源,取决于其实现——务必确认它在 close() 中调用了被包装流的 close()。
多资源声明顺序决定关闭安全
try-with-resources 按**声明的逆序**调用 close(),即后声明的先关闭。这对有依赖关系的资源至关重要:
- 缓冲流应声明在底层流之后(如
BufferedOutputStream在FileOutputStream后),确保先关缓冲层、再关文件句柄 - JDBC 资源推荐按
ResultSet → PreparedStatement → Connection的逆序声明,对应Connection → PreparedStatement → ResultSet的正向声明 - 避免在 try 块内对资源变量重新赋值(如
fis = new FileInputStream(...)),否则原引用丢失,无法自动关闭
别混用手动 close 和 try-with-resources
一旦使用 try-with-resources,就应彻底移除所有配套的 finally 块或 try 块内的手动 close() 调用。重复关闭会导致异常(如 "Stream closed"),污染异常堆栈,干扰问题定位。
若需兼容旧代码逻辑,宁可统一退回传统 try-catch-finally,也不要“双保险”式叠加。
异常抑制需主动检查
当 try 块抛出异常,且某个资源的 close() 也失败时,后者会被抑制(suppressed),附在主异常上,但不会自动打印。
排查问题时务必:
- 用
e.printStackTrace()或日志框架完整输出异常(含堆栈) - 显式检查
e.getSuppressed()数组,尤其在 IO 或数据库场景中 - 自定义
AutoCloseable实现时,close()方法内避免抛出未判空、未校验状态的异常
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











