finally块必定执行,除非JVM提前退出;它在return后执行但不改变已确定的返回值,典型用途是资源清理而非修正返回值。

finally 块在 try-catch 结构结束前**必定执行**,无论是否发生异常、是否被 catch 捕获、甚至在 try 或 catch 中用了 return,只要 try 语句块开始执行了,对应的 finally 就会执行(除非 JVM 直接退出)。
finally 在 return 之后执行,但不会改变已确定的返回值
很多人误以为 finally 里的 return 会覆盖前面的 return,其实不然。Java 的规则是:如果 try 或 catch 中有 return,JVM 会先记录下要返回的值(基本类型是值本身,引用类型是引用地址),然后去执行 finally;finally 执行完后,再把之前记下的值真正返回。
- try 中 return 5;finally 修改了变量 x = 10 → 最终仍返回 5
- try 中 return new StringBuilder("a");finally 调用 sb.append("b") → 返回对象内容变为 "ab"(因为是引用,对象被修改了)
- finally 里也写 return 3 → 这个 return 会生效,直接返回 3,覆盖之前的逻辑(不推荐这么写,容易掩盖问题)
哪些情况 finally 不会执行?
绝大多数情况下 finally 都会跑,但以下几种例外:
- JVM 在 try/catch 执行前就崩溃或被强制终止(如调用 System.exit(0))
- 线程被 kill(如 Thread.stop(),已废弃但理论上存在)
- 发生 StackOverflowError 或 OutOfMemoryError 等严重错误,且未被捕获(取决于 JVM 实现和错误时机)
- try 块还没来得及执行,比如方法刚进入就抛出异常(但此时连 try 都没进,自然没有对应的 finally)
finally 的典型用途
它不是用来“修正返回值”的,而是为资源清理而生:
立即学习“Java免费学习笔记(深入)”;
- 关闭文件流、数据库连接、Socket、锁(Lock.unlock())等必须释放的资源
- 恢复现场,比如重置标志位、还原线程局部变量(ThreadLocal)
- 日志记录:不管成功失败,都记一笔“操作结束”
基本上就这些。理解 finally 的执行时机,关键记住一点:它是 try-catch 生命周期的“收尾动作”,不是“兜底逻辑”。










