finally块必定执行,除非jvm强制终止或系统崩溃;无论try正常结束、抛异常未捕获、含return/break/continue/throw,均先执行finally再继续后续流程。

finally 代码块的核心保证是:无论 try 块中是否发生异常、是否被 catch 捕获、是否显式 return、break 或 continue,只要程序执行进入了 try 语句(即 try 块开始执行),那么对应的 finally 块就一定会被执行(除非 JVM 强制终止或底层系统崩溃)。
正常执行与异常未捕获时的执行
当 try 块顺利执行完毕,没有抛出异常,finally 会紧接着执行;如果 try 中抛出了异常且没有匹配的 catch 块处理,异常会向上传播,但 finally 仍会在异常传播前执行。
- try 正常结束 → finally 执行 → 后续代码继续
- try 抛出未被捕获的异常 → 先执行 finally → 再将异常向上抛出
return 语句存在时的执行顺序
即使 try 或 catch 中有 return,finally 也会在方法真正返回前执行。注意:若 finally 中也有 return,它会覆盖 try/catch 中的返回值(不推荐这种写法)。
- try 中 return 1; → 记录返回值 1 → 执行 finally → 最终返回 1(除非 finally 也 return)
- catch 中 return 2; → 同样先记录,再进 finally → 若 finally 无 return,则仍返回 2
- finally 中 return 3; → 会直接返回 3,并丢弃之前记录的返回值
控制流跳转(break/continue/throw)下的行为
在循环中嵌套 try-finally,或在 try 中使用 break、continue、throw,finally 依然保障执行。
- for 循环内 try 中 break → 跳出循环前先执行 finally
- try 中 throw 新异常 → 原异常被覆盖前,finally 仍会执行
- try 中 continue → 当前迭代结束前,finally 执行
不执行 finally 的极少数情况
这些属于非正常程序终止,不属于 Java 语言层面的“可控流程”:
- JVM 被强制退出(如 System.exit())
- 线程被 kill(如 Runtime.getRuntime().halt())
- 底层系统崩溃、断电、kill -9 进程等
- 死循环或无限递归导致栈溢出前未进入 finally(但一旦进入 try,就会走到 finally)









