因为 try-with-resources 会无条件调用 close(),jvm 保证执行,无需手动写 finally;资源须实现 autocloseable,关闭按声明逆序进行,异常通过 addsuppressed 附加,但资源泄漏仍可能发生。

为什么不用手动写 finally 关闭资源了
因为 try-with-resources 会在 try 块结束时**无条件调用 close()**,不管有没有 return、有没有异常、有没有提前跳出循环——JVM 层面保证执行,你根本不用操心它会不会被跳过。
- 传统
try-catch-finally容易漏掉close(),尤其在多层嵌套或多个 return 分支里 - 手动关资源还要处理
close()自己抛出的异常(比如IOException),容易掩盖主异常 -
try-with-resources内部会把close()异常用addSuppressed()附在主异常上,不丢信息也不干扰流程
哪些资源能用 try-with-resources
必须实现 AutoCloseable(或其子接口 Closeable)——不是有 close() 方法就行,得是接口契约声明过的。
- 标准库中绝大多数 I/O 类都符合:如
FileInputStream、BufferedReader、Socket、Connection、Statement - 自定义类要释放文件句柄、线程、本地内存等,也得显式
implements AutoCloseable并重写close() - 常见误区:
Thread、Timer、Scanner(没实现AutoCloseable)不能直接用,否则编译报错
多个资源怎么声明,关闭顺序是什么
用分号隔开多个资源声明,它们会按**声明的逆序**自动关闭——这是为了确保依赖关系不被破坏(比如包装流先关,底层流后关)。
try (FileInputStream fis = new FileInputStream("a.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("b.txt")) {
// ...
}
- 关闭顺序是:
bis→fis→fos(不是按字母或创建顺序) - Java 9 起支持“已声明变量复用”,比如
BufferedReader br = new BufferedReader(...); try (br) { ... },避免重复构造 - 如果某资源
close()抛异常,不影响后续资源关闭,但所有异常都会被收集和压制
最容易踩的坑:资源泄漏还在发生?
写了 try-with-resources 不等于万事大吉——资源泄漏照样可能发生,关键看 close() 里干了什么。
立即学习“Java免费学习笔记(深入)”;
- 资源类自己没正确实现
close():比如只关了缓冲区,忘了调super.close()或底层流 - 资源被提前
return或throw出 try 块,但 close 逻辑里又抛新异常且没处理好状态清理 - 多个资源间有共享状态(比如共用一个 socket),逆序关闭导致二次 close 或状态冲突
- 异步操作未等待完成就退出 try 块,资源被关但后台任务还在用 —— 这种得靠业务逻辑兜底,语法管不了
真正安全的资源管理,从来不只是语法糖的事;AutoCloseable 是契约,close() 是承诺,而你写的每一行清理代码,才是最后一道防线。










