Java 7 try-with-resources 要求资源必须实现 AutoCloseable 接口,Closeable 是其子接口;自定义类需显式 implements AutoCloseable,多资源用分号隔开且后声明先关闭,关闭异常被抑制可通过 getSuppressed() 获取。

Java 7 try-with-resources 要求资源必须实现 AutoCloseable
不是所有“带 close() 方法”的类都能放进 try-with-resources 里。Java 7 强制要求资源类型必须实现 AutoCloseable 接口(Closeable 是它的子接口,所以 FileInputStream、BufferedReader 这些都 OK)。如果你自己写的工具类只有 close() 方法但没实现该接口,编译直接报错:cannot be auto-closed; it does not implement AutoCloseable。
实操建议:
- 自定义资源类务必显式
implements AutoCloseable,哪怕只是简单委托给内部流 - 别依赖 IDE 自动生成的
close()—— 它不会帮你加接口声明 - 第三方库中某些老版本的流包装类(如早期 Apache Commons IO 的某些类)可能不满足条件,得手动关
多个资源怎么写\_分号隔开,关闭顺序和声明顺序相反
多个资源不能用逗号,必须用分号分隔;而且它们的 close() 调用顺序是「后声明,先关闭」——这很重要,尤其当资源之间有依赖时(比如 BufferedWriter 包裹 FileWriter),必须先关外层再关内层,否则可能丢数据或抛异常。
常见错误现象:写完文件没刷盘就关了底层流,导致内容截断;或者嵌套流关闭顺序反了,第二次 close() 抛 IOException。
立即学习“Java免费学习笔记(深入)”;
示例写法:
try (FileInputStream fis = new FileInputStream("a.txt");
BufferedInputStream bis = new BufferedInputStream(fis)) {
// 读操作
} // 先调 bis.close(),再调 fis.close()
catch 和 finally 还能用吗\_可以,但异常抑制机制要留意
try-with-resources 的 catch 块捕获的是业务代码或资源初始化阶段抛出的异常;而资源自动关闭时若也抛异常(比如网络流关闭失败),它会被「抑制(suppressed)」,默认不打断主异常流程,但可以通过 Throwable.getSuppressed() 拿到。
容易踩的坑:
- 如果 try 块没抛异常,但多个资源关闭都失败,只保留最后一个关闭异常,前面的被丢弃(除非你显式检查
getSuppressed()) -
finally块在 try-with-resources 中依然执行,但通常没必要——资源已经关了;重复关可能触发已关闭异常 - 不要在
catch里手动调fis.close(),会和自动关闭冲突,可能抛IOException
非 Java 7+ 环境或老 Android 怎么办\_别硬套,用工具类兜底
Java 6 或 Android API NoClassDefFoundError。这时候别改语言特性,用成熟方案更稳。
实操建议:
- Android 项目优先用
IOUtils.closeQuietly()(Apache Commons IO)或CloseableUtils.closeQuietly()(Guava) - 纯 Java 6 项目可封装一个静态工具方法,按顺序 try/catch 关每个资源,忽略关闭异常
- 千万别为了“优雅”在低版本上模拟语法糖——手写 try/finally 更清晰,也更容易 debug
最常被忽略的一点:IDE 自动补全或代码模板生成的 try-with-resources,可能悄悄把项目最低兼容版本抬高了,上线前记得核对 source 和 target 编译参数。










