finally不一定执行:System.exit()或halt()会直接终止JVM跳过它;守护线程中因JVM退出可能不运行;死锁或无限循环使程序无法到达;finally自身抛异常也会导致清理失败。

finally 块的执行机制是 Java 面试中高频考点,核心在于“何时执行”“是否一定执行”“与 return 的关系”三点。掌握清楚逻辑,就能稳答不卡壳。
finally 什么时候执行?
它总在 try 或 catch 执行完毕后、方法真正返回前执行——哪怕 try/catch 中有 return,JVM 也会先把返回值暂存,再进 finally,最后才完成返回。
- 无异常:try → finally
- 有异常且被 catch:try → catch → finally
- 有异常但未被捕获(向上抛):try → finally → 异常传播出去
- try 中有 return:return 值先缓存 → finally 执行 → 再返回缓存值(除非 finally 自己也 return)
finally 一定执行吗?
不是。两种典型情况会跳过它:
- 异常发生在 try 块之前(比如方法参数校验失败、static 初始化出错),根本没进入 try,自然不走 finally
- try 或 catch 中调用了 System.exit()、Runtime.getRuntime().halt() 等强制终止 JVM 的操作,程序直接退出
注意:return、throw、break、continue 都不影响 finally 执行;只有 JVM 被外力终结才会绕过。
立即学习“Java免费学习笔记(深入)”;
catch 里写了 return,finally 还会进去吗?
会。这是最容易被误解的一点。
- 基本类型(如 int、boolean):finally 中修改变量值无效,返回的是 catch 中 return 时已确定的值
- 引用类型(如 StringBuilder、List、自定义对象):finally 中对对象内容的修改会保留,因为返回的是对象引用,而对象本身在堆中被改了
- 如果 finally 里也有 return,它会覆盖前面所有 return,成为最终返回结果(但实际开发中应避免这么写)
finally 最常见的用途是什么?
资源清理——这是设计它的本意。
- 关闭文件流(InputStream/OutputStream)
- 释放数据库连接(Connection、Statement、ResultSet)
- 解锁 ReentrantLock(lock.unlock())
- 注意:Java 7+ 推荐用 try-with-resources 替代手动 finally 关闭,更简洁安全


















