推荐优先使用 try-with-resources(jdk 7+)替代 finally 中手动 close(),它自动按逆序关闭资源、抑制关闭异常且不掩盖主异常;若必须手动关闭,需对每个资源判空并独立 try-catch。

在 Java 中,finally 块中手动调用 Closeable.close() 容易出错,尤其是嵌套 try 时——可能引发重复关闭、NullPointerException 或掩盖原始异常。推荐用更安全、简洁的方式替代手动 finally 关闭。
优先使用 try-with-resources(JDK 7+)
这是最推荐的做法:自动管理资源生命周期,无需显式 finally,支持多资源声明,且能正确抑制(suppressed)关闭异常,不掩盖主异常。
例如嵌套资源(如 BufferedReader 包裹 FileInputStream)可直接并列声明:
try (FileInputStream fis = new FileInputStream("a.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(fis))) {
String line = reader.readLine();
// 处理逻辑
} catch (IOException e) {
// 处理业务异常
}
注意:资源按声明**逆序**关闭(reader 先关,再关 fis),且每个 close() 异常都会被自动抑制,可通过 e.getSuppressed() 获取。
若必须用传统 try-finally,避免在 finally 中裸调 close()
手动关闭需防御性检查和异常捕获,否则可能因 null 或已关闭资源抛出异常,干扰主流程。
- 始终判空:资源变量可能为
null(如构造失败) - 每个
close()单独包裹try-catch,防止一个关闭失败阻断后续关闭 - 不要把
close()放在同一个catch或外层finally中“统一处理”,容易遗漏或顺序错误
示例(安全的手动写法):
FileInputStream fis = null;
BufferedReader reader = null;
try {
fis = new FileInputStream("a.txt");
reader = new BufferedReader(new InputStreamReader(fis));
// 业务逻辑
} catch (IOException e) {
// 处理异常
} finally {
if (reader != null) {
try { reader.close(); } catch (IOException ignored) {}
}
if (fis != null) {
try { fis.close(); } catch (IOException ignored) {}
}
}
嵌套 try 的典型陷阱与规避
嵌套 try(比如外层 try 管理 A 资源,内层 try 管理 B 资源)易导致关闭逻辑分散、重复或遗漏。常见问题包括:
- 内层
finally关闭了被外层依赖的资源(如提前关fis,导致reader后续操作失败) - 异常从内层抛出后,外层
finally未执行,资源泄漏 - 多个
close()都抛异常,只有最后一个被抛出,前面的丢失
解决思路:尽量扁平化结构,用 try-with-resources 替代嵌套;若必须嵌套,确保资源作用域清晰、关闭顺序合理,并始终用独立 try-catch 包裹每个 close()。
自定义工具方法简化手动关闭(慎用)
可封装一个静态工具方法降低样板代码,但要注意它不能替代 try-with-resources 的异常抑制能力:
public static void closeQuietly(Closeable... closables) {
for (Closeable c : closables) {
if (c != null) {
try { c.close(); } catch (IOException ignored) {}
}
}
}
使用:finally { closeQuietly(reader, fis); }。适合遗留代码改造,但新代码仍应首选 try-with-resources。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











