try-with-resources 强制调用 close() 并正确处理异常传播,要求资源实现 AutoCloseable;多资源按声明逆序关闭;主异常优先,close 异常被抑制并可获取;建议显式 flush 以提升可靠性。

try-with-resources 能确保 IO 流被安全关闭,但“安全”不等于“静默”或“无异常”,关键在于它**强制调用 close() 方法,并正确处理关闭过程中的异常传播逻辑**。
必须满足的前提条件
只有实现了 AutoCloseable(或其子接口 Closeable)的类才能用于 try-with-resources。Java 标准库中绝大多数 IO 类都满足这一要求,例如:
-
FileInputStream/FileOutputStream -
BufferedReader/BufferedWriter -
ObjectInputStream/ObjectOutputStream -
ZipInputStream/ZipOutputStream
自定义类若需支持该语法,也必须实现 AutoCloseable 并在 close() 中释放底层资源。
多资源声明与关闭顺序
可以在 try 括号内用分号分隔多个资源,它们按**声明顺序的逆序**关闭——即后声明的先关闭,先声明的后关闭。这对嵌套流尤其重要:
- 正确写法(推荐):
try (FileInputStream fis = new FileInputStream("a.txt");<br> BufferedInputStream bis = new BufferedInputStream(fis)) { ... }
→ 先关bis,再关fis,避免重复关闭或操作已释放句柄 - 错误写法:
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"))) { ... }
虽可运行,但外层流未显式管理,一旦bis.close()抛异常,底层fis的关闭可能失败或被掩盖
异常处理机制:主异常优先,关闭异常被抑制
当 try 块本身抛出异常,且资源 close() 也抛异常时,JVM 不会丢弃任一异常:
- try 块的异常作为主异常抛出
- 各资源
close()抛出的异常会被添加为 suppressed exception(被抑制异常) - 可通过
exception.getSuppressed()获取这些关闭异常,便于诊断
这意味着:你不会“看不见”关闭失败,只是它不打断主流程;若需排查写入失败(如磁盘满导致 BufferedOutputStream.close() 报错),必须检查 suppressed 异常。
提升关闭可靠性的小实践
避免把所有希望寄托在 close() 上,尤其对带缓冲或压缩的流:
- 在 try 块末尾显式调用
flush(),提前暴露写入问题,让close()只做句柄释放 - 对关键业务(如日志落盘、配置保存),不要依赖“自动关闭即成功”,应在 close 前确认数据已持久化
- 慎用自行封装的“静默关闭”包装类(如吞掉
IOException的QuietCloseable),除非明确接受数据丢失风险
不复杂但容易忽略










