优先用try-with-resources替代finally;必须用finally时需判空、独立捕获异常、不return;针对lock、executorservice、native内存等资源有特定释放规则;finally在jvm强制终止等极端情况下不执行。

在finally块中释放资源,关键不是“能不能执行”,而是“能不能安全执行”——既要确保资源真被关掉,又不能掩盖原始异常、引发NPE或导致死锁。最稳妥的做法是:能不用finally就不用,优先选try-with-resources;非用不可时,必须守住判空、独立捕获、不return这三条底线。
优先用try-with-resources替代手写finally
Java 7起支持的try-with-resources是释放AutoCloseable资源(如FileInputStream、Connection、Scanner等)的首选方式:
- 资源在try括号内声明,作用域明确,JVM自动按“后声明先关闭”顺序调close()
- 即使try块和close()都抛异常,主异常仍保留,close异常作为suppressed exception附加,可通过
e.getSuppressed()查看 - 无需判空、无需手动写finally、代码行数减半,基本杜绝空指针和遗漏关闭
必须用finally时,按三步写才安全
适用于非AutoCloseable资源(如ReentrantLock、ExecutorService、Unsafe分配的native内存)或需兼容老JDK的场景:
-
变量声明在try外、初始化为null:避免作用域不可见,比如
Lock lock = null; - 每个资源单独判空+单独try-catch:一个close失败不能影响另一个,例如关闭InputStream和OutputStream要分开处理
- finally里绝不写return或throw:否则会吞掉try/catch里的返回值或异常,让问题难以定位
针对不同资源类型的操作要点
不是所有资源都能套用同一模板:
-
Lock类资源:先
lock.lock()再进try,finally里直接lock.unlock()——不要加isHeldByCurrentThread()判断,既不必要也不安全 -
ExecutorService:finally中调
shutdown(),再用awaitTermination(30, TimeUnit.SECONDS)等待,超时后考虑shutdownNow() -
native内存或自定义资源:必须显式释放;Java 9+可配合
Cleaner做兜底,但不能替代finally中的主动释放
finally不是100%可靠,但你得知道边界
绝大多数情况下finally会执行,但有三个明确例外:
- JVM被强制终止(如
System.exit(0)、kill -9) - 线程被中断且未响应中断状态(极少见)
- 发生致命错误(如OutOfMemoryError导致JVM崩溃)
日常开发中只需关注逻辑正确性,这些极端情况通常不在应用层处理范畴。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











