finally块总在try中return暂存返回值后、方法真正返回前执行;若finally含return则覆盖原返回值,否则返回try中暂存的值。

当 try 块中遇到 return 语句时,finally 块一定会执行,且在 return 的实际返回值被送出前执行。这不是“先 return 再 finally”,而是“准备返回 → 执行 finally → 完成返回”。关键在于:return 并不立即退出方法,而是暂存返回值,等 finally 走完再交出结果。
try 中 return 的本质是“缓存返回值”
Java(及类似 JVM 语言)在编译后,try 中的 return 实际会被拆解为两步:
- 计算 return 表达式的值(如
return x + 1,先算出结果并暂存) - 标记“即将返回”,但不真正跳出去——JVM 会确保 finally 先跑完
这个暂存值存在“本地变量槽”或操作数栈中,后续可能被 finally 中的代码间接影响(比如修改了影响该值的对象状态),但不会被 finally 中的 return 覆盖原始返回意图(除非 finally 自己也 return)。
finally 在 return 之后、方法真正退出之前运行
执行顺序严格如下(以一个有 return 的 try 为例):
- 进入 try 块
- 执行到 return 语句 → 计算返回值(例如
return getValue(),调用 getValue() 并拿到结果) - 暂存该结果,标记“待返回”
- 跳转去执行 finally 块(无论 try 是正常 return 还是抛异常,finally 都走这一步)
- finally 执行完毕(注意:若 finally 里也有 return,它会直接终结方法,覆盖 try 中的返回值)
- 把最初暂存的返回值送出(除非被 finally 的 return 截断)
finally 中 return 会劫持整个返回流程
这是最容易踩坑的点:一旦 finally 中出现 return,它将无视 try 或 catch 中的任何 return,直接作为方法的最终返回值。
示例:
public static int test() {
try {
return 1;
} finally {
return 2; // ✅ 方法永远返回 2,try 中的 1 被丢弃
}
}
同理,如果 finally 抛出异常,也会吞掉 try 中的 return,导致方法以异常结束。
finally 可以修改对象状态,从而“间接改变返回值”
对于引用类型,虽然返回值本身(即对象引用)在 try 中已确定,但如果该对象的内部状态在 finally 中被修改,调用方看到的就是修改后的状态。
示例:
public static StringBuilder test() {
StringBuilder sb = new StringBuilder("hello");
try {
return sb; // 返回的是 sb 这个引用
} finally {
sb.append(" world"); // ✅ 修改了原对象内容
}
}
// 调用方拿到的是 "hello world",不是 "hello"
这是因为 return 的是引用,不是深拷贝;finally 操作的是同一个对象。











