Java安全关闭文件资源首选try-with-resources,自动按逆序关闭并抑制close异常;次选finally中判空+独立捕获关闭,确保所有执行路径下资源必关。

Java 中安全关闭文件读写资源,核心就两条路:优先用 try-with-resources,实在不行再用 try-catch-finally + 判空 + 嵌套异常处理。关键不是“关没关”,而是“是否保证在所有路径下都关了”,包括构造失败、业务异常、甚至 JVM 级错误。
推荐方式:用 try-with-resources 自动管理
这是 Java 7 起的标准做法,适用于所有实现 AutoCloseable 的资源(FileInputStream、BufferedReader、FileWriter 等全支持)。
- 资源声明直接写在
try括号里,多个用分号隔开 - JVM 会在 try 块结束时(无论正常退出还是抛异常)自动调用
close() - 如果多个资源,按声明**逆序**关闭(后声明的先关),避免依赖冲突
-
close()抛出的异常会被“抑制”(suppressed),主业务异常仍可被捕获和打印
示例:
try (BufferedReader reader = new BufferedReader(new FileReader("data.txt"));
BufferedWriter writer = new BufferedWriter(new FileWriter("out.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
writer.write(line.toUpperCase());
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
备用方式:手动关闭必须放在 finally 里
仅当资源不实现 AutoCloseable(极少见),或需在关闭前做额外清理逻辑时才用。此时必须严格遵循以下结构:
- 资源变量声明为
null,并在 try 外初始化 -
close()只能写在finally块中,不能放 try 或 catch 里 - 每次
close()前必须判空,因为构造可能失败(如文件不存在导致new FileInputStream()抛异常,变量仍是null) - 每个
close()都要单独包一层try-catch,防止一个流关闭失败影响另一个
示例:
FileInputStream fis = null;
BufferedInputStream bis = null;
try {
fis = new FileInputStream("in.txt");
bis = new BufferedInputStream(fis);
// 读取操作
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bis != null) {
try { bis.close(); } catch (IOException ignored) {}
}
if (fis != null) {
try { fis.close(); } catch (IOException ignored) {}
}
}
容易踩的坑
- 把
close()写在 try 块末尾:前面一抛异常,就跳过关闭 - 只判一次空、共用一个
try-catch关多个流:一个close()失败,后续流就漏关 - 忽略
close()可能抛IOException:不捕获也不声明,编译不过或运行崩溃 - 认为“catch 住异常就安全了”:没关资源照样泄漏,连接池耗尽、文件句柄占满都是真实线上事故
一句话总结
现代 Java 开发中,95% 以上的 IO 资源关闭场景,直接用 try (Resource r = ...) 就完事;剩下那 5%,是历史代码、特殊框架资源或需要定制清理逻辑——这时才动手写 finally,且务必每步判空、各自捕获。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











