当 try 代码块中遇到 return 语句时,Java 并不会立即返回,它会执行以下两个步骤:

- 计算
return语句的返回值,这个值会被“暂存”起来。 - 执行
finally代码块(如果存在)。 - 在
finally执行完毕后,才会将之前暂存的返回值真正返回出去。
finally 代码块的执行优先级高于 try 或 catch 中的 return 语句。
示例代码与分析
我们通过几个例子来深入理解。
示例 1:标准情况(有 finally)
public class TryReturnExample {
public static int testReturnInTry() {
int result = 0;
try {
System.out.println("Try block is executed.");
result = 10;
return result; // 1. 计算 return 值 (10),暂存它,但不立即返回
} finally {
System.out.println("Finally block is executed.");
result = 20; // 2. finally 块修改了这个变量的值
}
// 3. finally 执行完毕后,返回之前暂存的值 10
}
public static void main(String[] args) {
int returnValue = testReturnInTry();
System.out.println("Method returned: " + returnValue);
}
}
执行结果:
Try block is executed.
Finally block is executed.
Method returned: 10
步骤分析:

try块中的代码执行,result被赋值为10。- 遇到
return result;,JVM 计算result的值,即10,并将这个值10放在一个“临时返回值”的寄存器或内存位置中。 - 在执行
return之前,程序必须先执行finally块。 finally块被执行,打印日志,并将result的值修改为20。注意:这个修改只影响了result这个局部变量,并不会影响已经暂存好的返回值。finally块执行完毕。- 程序从“临时返回值”的位置取出
10,并将其作为整个方法的返回值返回。 main方法打印出10。
finally 块中对变量的修改,不会影响到 try 中 return 语句已经计算好的返回值。
示例 2:finally 块中也包含 return
这是一个更极端但可能被问到的情况。
public class TryReturnWithFinallyReturn {
public static int testReturnInFinally() {
try {
System.out.println("Try block is executed.");
return 10; // 暂存返回值 10
} finally {
System.out.println("Finally block is executed.");
return 30; // 1. 这个 return 会覆盖掉 try 中暂存的 return
}
// 2. 方法从这里返回,返回值是 30
}
public static void main(String[] args) {
int returnValue = testReturnInFinally();
System.out.println("Method returned: " + returnValue);
}
}
执行结果:
Try block is executed.
Finally block is executed.
Method returned: 30
步骤分析:

try块执行,遇到return 10;,返回值10被暂存。- 程序跳转到
finally块执行。 finally块中遇到了return 30;,这个return语句会覆盖掉之前暂存的10。- 方法立即以
30作为返回值返回,不会再回到try块的return处。
重要提示: 在 finally 块中使用 return 是一种非常糟糕的编程实践,它会隐藏原始的异常(如果有的话)或 try/catch 中的返回值,使得代码逻辑变得难以理解和调试。永远不要在 finally 块里使用 return。
示例 3:try 中有 return,catch 中也有 return
这个例子展示了异常处理流程与 return 的结合。
public class TryCatchReturnExample {
public static int testReturnInTryCatch() {
try {
System.out.println("Try block is executed.");
int a = 10 / 0; // 这行代码会抛出 ArithmeticException
return 10; // 这行代码不会执行
} catch (Exception e) {
System.out.println("Catch block is executed.");
return 20; // 1. 暂存返回值 20
} finally {
System.out.println("Finally block is executed.");
}
// 2. finally 执行完毕后,返回之前暂存的值 20
}
public static void main(String[] args) {
int returnValue = testReturnInTryCatch();
System.out.println("Method returned: " + returnValue);
}
}
执行结果:
Try block is executed.
Catch block is executed.
Finally block is executed.
Method returned: 20
步骤分析:
try块开始执行。int a = 10 / 0;抛出ArithmeticException。try块中剩下的代码(包括return 10;)被跳过。- 程序跳转到匹配的
catch块。 catch块执行,打印日志,遇到return 20;,返回值20被暂存。- 在执行
return之前,程序必须先执行finally块。 finally块被执行并打印日志。finally块执行完毕。- 方法返回之前暂存的值
20。
| 场景 | try 中有 return |
catch 中有 return |
finally 中有 return |
最终返回值 | 说明 |
|---|---|---|---|---|---|
| 标准情况 | return value; |
- | 无 return |
try 中暂存的 value |
finally 执行后返回 try 的值。 |
finally 覆盖 |
return value1; |
- | return value2; |
finally 中的 value2 |
强烈不推荐,finally 的 return 会覆盖掉之前的。 |
| 异常情况 | 抛出异常 | return value; |
无 return |
catch 中暂存的 value |
异常发生,try 的 return 被跳过,执行 catch 的 return 流程。 |
异常 + finally 覆盖 |
抛出异常 | return value1; |
return value2; |
finally 中的 value2 |
强烈不推荐,finally 的 return 会覆盖掉 catch 的。 |
核心要点:
finally的设计初衷是为了执行“无论如何都必须执行的清理代码”,例如关闭文件、释放数据库连接等。finally的执行优先级是最高的,它总是在try或catch的return语句之前执行。try中return的返回值会被“快照”下来,finally块中对原始变量的修改不会影响这个快照。- 绝对避免在
finally块中使用return,因为它会破坏异常处理机制和正常的返回流程,导致代码行为混乱且难以调试。
