优先用try-with-resources;手动finally需提前声明资源变量、每个close()单独判空并捕获异常、按后开先关顺序关闭、不在finally中return或throw,以确保资源安全释放。

在finally块中安全关闭流资源,关键不是“只要写了finally就万事大吉”,而是确保每个close()调用都独立、判空、捕获异常,并且不干扰主流程。更根本的是:优先用try-with-resources;只有在必须兼容老JDK或处理非AutoCloseable资源时,才需手动写finally。
资源变量必须声明在try外部
如果在try里new FileInputStream,那finally根本访问不到这个变量——编译直接报错。正确做法是提前声明并初始化为null:
- FileInputStream fis = null;
- BufferedInputStream bis = null;
- OutputStream out = null;
每个资源都要单独判空+单独try-catch关闭
close()可能抛IOException,一个资源关闭失败不能让其他资源跳过。也不能把多个close()塞进同一个try里——前一个抛异常,后一个就执行不到。
- if (bis != null) { try { bis.close(); } catch (IOException e) { /* 记日志 */ } }
- if (fis != null) { try { fis.close(); } catch (IOException e) { /* 记日志 */ } }
- 关闭顺序建议按“后打开先关闭”(如bis包装fis,则先关bis再关fis)
别在finally里return或throw
finally里return会覆盖try或catch中的返回值;throw新异常会吞掉原始异常,导致问题难以定位。
- 即使close()失败,也只应记录日志或忽略,不要向上抛
- Java 7+的try-with-resources会在异常发生时自动压制close异常,主异常仍可被捕获和分析
为什么try-with-resources是首选
它不是语法糖,而是JVM级保障:
- 资源声明即生效,作用域清晰,无需手动判空
- 自动按逆序调用close(),嵌套流(如BufferedInputStream包裹FileInputStream)也能正确释放
- 若try块和close()都抛异常,后者会被suppress,原始异常仍是栈顶主因
- 代码行数减少约50%,逻辑一目了然
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











