finally 中的 return 会强制覆盖 try/catch 的返回值,JVM 以 finally 的退出指令为准;若 finally 抛异常,则压制原异常;因此 finally 中不应含 return,仅用于资源清理。
finally 中写 return 会覆盖 try/catch 的返回值
Java 规定:只要 finally 块中存在 return,无论 try 或 catch 是否已执行过 return,最终方法返回的都是 finally 中的值。这不是“覆盖”语义上的覆盖,而是 JVM 字节码层面强制以 finally 的退出指令为准。
-
try中return 1;→ 表达式求值并暂存返回值,但不立即退出 - 接着执行
finally块 -
finally中若有return 2;→ 直接返回2,丢弃之前暂存的1 - 若
finally没有return,才真正返回try或catch中暂存的值
try/catch/finally 的执行顺序与异常传播关系
关键在于:异常是否被 catch,以及 finally 是否抛出新异常或 return。JVM 执行流程是确定的:
- 正常流程(无异常):
try→finally→ 方法返回 - 异常未被捕获:
try抛异常 →finally执行 → 异常继续向上抛 - 异常被
catch处理:try→catch→finally→ 返回或继续抛 -
finally中抛出异常:会压制try或catch中的异常(即原异常丢失),仅传播finally的异常
return 在 finally 中的典型陷阱示例
下面这段代码返回结果是 2,不是 1,也不是抛出 NullPointerException:
public static int getValue() {
int x = 0;
try {
return x = 1;
} finally {
return x = 2;
}
}
更危险的是这个情况: