杰瑞科技汇

try中return,finally会执行吗?

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

try中return,finally会执行吗?-图1
(图片来源网络,侵删)
  1. 计算 return 语句的返回值,这个值会被“暂存”起来。
  2. 执行 finally 代码块(如果存在)。
  3. finally 执行完毕后,才会将之前暂存的返回值真正返回出去

finally 代码块的执行优先级高于 trycatch 中的 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中return,finally会执行吗?-图2
(图片来源网络,侵删)
  1. try 块中的代码执行,result 被赋值为 10
  2. 遇到 return result;,JVM 计算 result 的值,即 10,并将这个值 10 放在一个“临时返回值”的寄存器或内存位置中。
  3. 在执行 return 之前,程序必须先执行 finally 块。
  4. finally 块被执行,打印日志,并将 result 的值修改为 20注意:这个修改只影响了 result 这个局部变量,并不会影响已经暂存好的返回值。
  5. finally 块执行完毕。
  6. 程序从“临时返回值”的位置取出 10,并将其作为整个方法的返回值返回。
  7. main 方法打印出 10

finally 块中对变量的修改,不会影响到 tryreturn 语句已经计算好的返回值。


示例 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,finally会执行吗?-图3
(图片来源网络,侵删)
  1. try 块执行,遇到 return 10;,返回值 10 被暂存。
  2. 程序跳转到 finally 块执行。
  3. finally 块中遇到了 return 30;,这个 return 语句会覆盖掉之前暂存的 10
  4. 方法立即以 30 作为返回值返回,不会再回到 try 块的 return 处。

重要提示:finally 块中使用 return 是一种非常糟糕的编程实践,它会隐藏原始的异常(如果有的话)或 try/catch 中的返回值,使得代码逻辑变得难以理解和调试。永远不要在 finally 块里使用 return


示例 3:try 中有 returncatch 中也有 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

步骤分析:

  1. try 块开始执行。
  2. int a = 10 / 0; 抛出 ArithmeticException
  3. try 块中剩下的代码(包括 return 10;)被跳过。
  4. 程序跳转到匹配的 catch 块。
  5. catch 块执行,打印日志,遇到 return 20;,返回值 20 被暂存。
  6. 在执行 return 之前,程序必须先执行 finally 块。
  7. finally 块被执行并打印日志。
  8. finally 块执行完毕。
  9. 方法返回之前暂存的值 20

场景 try 中有 return catch 中有 return finally 中有 return 最终返回值 说明
标准情况 return value; - return try 中暂存的 value finally 执行后返回 try 的值。
finally 覆盖 return value1; - return value2; finally 中的 value2 强烈不推荐finallyreturn 会覆盖掉之前的。
异常情况 抛出异常 return value; return catch 中暂存的 value 异常发生,tryreturn 被跳过,执行 catchreturn 流程。
异常 + finally 覆盖 抛出异常 return value1; return value2; finally 中的 value2 强烈不推荐finallyreturn 会覆盖掉 catch 的。

核心要点:

  1. finally 的设计初衷是为了执行“无论如何都必须执行的清理代码”,例如关闭文件、释放数据库连接等。
  2. finally 的执行优先级是最高的,它总是在 trycatchreturn 语句之前执行。
  3. tryreturn 的返回值会被“快照”下来,finally 块中对原始变量的修改不会影响这个快照。
  4. 绝对避免在 finally 块中使用 return,因为它会破坏异常处理机制和正常的返回流程,导致代码行为混乱且难以调试。
分享:
扫描分享到社交APP
上一篇
下一篇