优先使用try-with-resources替代finally释放资源,因其自动按序关闭autocloseable资源、抑制close异常、避免资源泄漏;若必须用finally,则需外部声明变量、判空并独立try-catch关闭每个资源。

Java中在finally块中正确释放资源,核心是确保关闭逻辑一定会执行、每个资源都独立处理、不因一个异常掩盖另一个。但更关键的是:优先不用finally——改用try-with-resources。
为什么finally容易出问题
手动在finally里关资源,常见陷阱包括:
- 多个资源时,前一个close()抛异常,后续资源就跳过了
- 忘记判空(比如流为null时调close()会NPE)
- close()本身可能抛IOException,若没捕获,会吞掉原异常或中断流程
- 变量作用域写错,比如fis在try内声明,finally里根本访问不到
传统finally写法的要点
如果必须用try-catch-finally(例如兼容老JDK或非AutoCloseable资源),请按这个结构写:
- 资源变量声明在try外部,初始化为null
- finally中对每个资源单独判空+单独try-catch关闭
- 不要在finally里return或throw,避免干扰主流程
示例:同时关InputStream和OutputStream
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream("in.txt");
out = new FileOutputStream("out.txt");
// 读写操作
} catch (IOException e) {
// 处理业务异常
} finally {
if (in != null) {
try { in.close(); } catch (IOException e) { /* 记日志,不抛出 */ }
}
if (out != null) {
try { out.close(); } catch (IOException e) { /* 记日志,不抛出 */ }
}
}
推荐方案:用try-with-resources替代finally
Java 7起支持,自动关闭所有实现AutoCloseable的资源(FileInputStream、Connection、Scanner等全支持):
- 资源在try括号内声明,作用域严格限定
- 无论是否异常,JVM保证按“后声明先关闭”顺序调close()
- 即使try块抛异常,close()异常会被压制(suppressed),主异常仍可捕获
- 代码行数减少一半,逻辑清晰,基本杜绝泄漏
示例:嵌套流自动关闭
try (FileInputStream fis = new FileInputStream("data.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(fis))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
// 这里捕获的是try块中的异常;fis和reader的close()异常已压制
}
自定义资源也得能自动关
如果你自己写的类需要被try-with-resources管理,只需实现AutoCloseable接口:
- 重写close()方法,在里面做清理(如释放锁、清缓存、关socket)
- 注意close()内部别抛受检异常,或声明throws Exception(不推荐)
- 避免在close()里做耗时或可能死锁的操作
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











