finally块确保代码确定性执行,不捕获异常也不自动释放资源,需显式调用close()等;即使try抛异常或含return,finally仍执行,但其抛出的异常会覆盖原异常。

在 Java 中,finally 块是确保资源释放的可靠机制,但它本身不处理异常,而是保证无论是否发生异常、是否 return,只要 try 块开始执行,finally 就一定会运行(除非 JVM 强制退出或线程被杀死)。
finally 能做什么、不能做什么
finally 的核心价值在于“确定性执行”,不是“异常捕获”。它不会阻止异常传播,也不会自动关闭资源——你需要在 finally 里显式调用 close()、release() 等方法。
- 即使 try 中抛出未捕获异常,finally 仍会执行
- 即使 try 或 catch 中有 return,finally 也会先执行再返回
- 但若 finally 中也抛出异常,它会覆盖 try/catch 中的异常(需谨慎)
手动在 finally 中释放资源的写法
适用于老版本 Java(
InputStream in = null;
try {
in = new FileInputStream("file.txt");
// 读取操作
} catch (IOException e) {
// 处理读取异常
} finally {
if (in != null) {
try {
in.close(); // 可能抛 IOException
} catch (IOException e) {
// 记录 close 失败,但不 throw(否则掩盖原始异常)
System.err.println("关闭输入流失败: " + e.getMessage());
}
}
}
优先使用 try-with-resources(推荐)
Java 7+ 引入的语法糖,自动管理实现了 AutoCloseable 的资源。它本质是在编译期生成等效的 finally 关闭逻辑,更简洁、更安全。
- 资源必须声明在 try 后的括号中,且类型实现 AutoCloseable
- 多个资源用分号隔开,关闭顺序与声明顺序相反(后声明先关闭)
- 即使 try 中抛异常,所有已成功初始化的资源都会被自动关闭
try (FileInputStream in = new FileInputStream("file.txt");
FileOutputStream out = new FileOutputStream("out.txt")) {
// 读写操作
// 若此处抛异常,in 和 out 仍会被依次关闭
} catch (IOException e) {
// 处理业务异常
}
注意 finally 中的 return 和异常覆盖
如果 finally 中有 return 或抛出异常,它会干扰原异常流程,导致调试困难。
- try 中 throw RuntimeException,finally 中 return 1 → 方法返回 1,原始异常丢失
- try 中 throw Exception,finally 中 throw AnotherException → 抛出的是 AnotherException,原异常被压制(可通过 getSuppressed() 获取)
- 结论:finally 中尽量只做清理,不要 return,也不要主动 throw
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











