finally总在try或catch执行完后、方法返回前执行,无论是否异常或return;若finally含return则覆盖原返回值;System.exit()等极少数情况不执行。

在Java中,try块先执行,finally块在try(或catch)执行完毕后、方法返回前执行——但要注意:它不“插队”,而是严格遵循控制流的退出时机。
try和finally的基本执行顺序
Java规定,只要进入了try语句块(哪怕只执行了一行),无论是否发生异常、是否执行了return、break或continue,只要该try对应的finally存在且未被JVM强制终止(如System.exit()),finally一定会被执行,且是在try或catch语句全部执行完之后、控制权交还给调用方之前运行。
- 正常流程:try → finally → 方法后续代码(或返回)
- 抛异常但被catch:try(到异常处)→ catch → finally → 方法后续代码(或返回)
- 抛异常未被catch:try(到异常处)→ finally → 异常向上抛出
- try中有return:return表达式先计算并暂存结果 → finally执行 → 再真正返回(注意:若finally里也有return,会覆盖原返回值)
finally在return之后“插手”的真实含义
很多人误以为“finally在return之后执行”意味着return已经完成。实际上,return不是瞬间完成的动作,它包含两个阶段:① 计算返回值并暂存;② 跳转离开当前方法。finally就插在这两个阶段之间。
例如:
立即学习“Java免费学习笔记(深入)”;
public static int test() {
try {
return 1;
} finally {
System.out.println("finally run");
// 此处若写 return 2; 就会覆盖原来的1
}
}
输出是"finally run",返回值是1;但如果finally里也写return 2,最终返回的就是2——因为finally的return会中断原返回流程,直接跳转出去。
哪些情况finally不会执行?
绝大多数情况下finally都会执行,但以下几种例外:
- JVM退出:如调用System.exit()
- 线程被强制中断(Thread.stop(),已废弃,但极端情况下可能影响)
- finally所在代码段根本没进入:比如try之前就抛出了Error(如StackOverflowError),且未被外层捕获
- 死循环或无限等待卡在try/catch中,程序未退出,finally自然也不会触发
实际开发中的关键提醒
不要在finally里修改返回值,除非你明确需要覆盖逻辑(比如日志兜底、资源强制重置);更不要在finally里抛出新异常——它会吞掉原异常,导致问题难以排查。
释放资源(如关闭IO流、数据库连接)是finally的经典用途,但自Java 7起,优先推荐使用try-with-resources语法,它更简洁且能自动处理资源关闭,底层仍依赖类似finally的机制。










