Java中try、catch、finally语句块的执行顺序

Java try-catch-finally详解
本文通过六个具体场景详细解析了Java中try-catch-finally语句块的执行顺序及注意事项,包括不同情况下return语句的行为差异以及引用类型对象在finally块中被修改的影响。

一、我们将try{}catch(){}finally{}分成以下几种情况分别验证:

场景1:try{return;}catch{}finally{} return;

    public static int returnSttat(int i) {
        System.out.println("return block");
        return i;
    }

    public static int test01() {
        int i = 0;
        try {
            i = 1;
            return returnSttat(i);
        }catch (Exception e) {

        } finally {
            System.out.println("finally block01");
        }
        return 0;
    }

执行结果如下:

return block
finally block01
1

执行步骤: a) 执行try{}部分(包括return表达式); b) 执行finally{}部分; c) 返回try{}中return表达式结果.

场景2:try{}catch{}finally{} return 有异常场景;

    public static int returnSttat(int i) {
        System.out.println("return block");
        return i;
    }
    public static int test01() {
        int i = 1;
        int divid = 0;
        try {
            int n = i / divid;
        } catch (Exception e) {
            System.out.println("catch block");
            return returnSttat(i);
        } finally {
            System.out.println("finally block");
        }
        return 0;
    }

执行结果如下:

catch block
return block
finally block
1

执行顺序: a) 执行try块抛出异常;b)catch拦截了异常并执行处理逻辑; c) 执行try中return 表达式;d)执行finally块; e) 执行return表达式返回值

场景3: try{return;} catch{} finally{return;}

    public static int returnSttat(int i) {
        System.out.println("return block");
        return i;
    }
    public static int test01() {
        int i = 1;
        try {
            System.out.println("try block");
            return returnSttat(i);
        } catch (Exception e) {
            System.out.println("catch block");
        }finally {
            System.out.println("finally block");
            return returnSttat(0);
        }
    }

执行结果如下:

try block
return block
finally block
return block
0

执行顺序: a) 执行try块,并执行其中return表达式; b) 执行finally块; c) 执行finally中return 表达式;d) 返回finally中return表达式结果(PS:由于finally中有return语句则直接返回退出)

场景4:try{return;} catch{} finally{return;}有异常

    public static int returnSttat(int i) {
        System.out.println("return block" + i);
        return i;
    }
    public static int test01() {
        int i = 1;
        int j = 0;
        try {
            System.out.println("try block");
            int k = i / j;
            return returnSttat(i);
        } catch (Exception e) {
            System.out.println("catch block");
            return returnSttat(-1);
        }finally {
            System.out.println("finally block");
            return returnSttat(0);
        }
    }

执行结果:

try block
catch block
return block-1
finally block
return block0
0

执行顺序: a) 执行try块,并抛出异常; b) catch获取异常,执行其中语句,并执行其中return语句;c) 执行finally块中语句并执行return语句;d)返回finally语句中return结果集(由于finally中有return则直接返回退出)

场景5: try{}finally{}中引用类型对象发生修改

    public static User test01() {
        User user = new User("kk");
        try{
            System.out.println("try block: " + user);
            return user;
        } finally {
            System.out.println("finally block: " + user);
            user.name = "jj";
        }
    }

    static class User {
        String name;
        User(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return hashCode() + ":"+ name;
        }
    }

执行结果:

try block: 780376:kk
finally block: 780376:kk
780376:jj

执行步骤: a) 执行try{}中块并执行return user语句;b)执行finally语句修改了u的属性name;c)返回u。(PS user属性竟然发生改变啦!)

场景6: try{}finally{}中引用类型对象返回

    public static User test01() {
        User user = new User("kk");
        try{
            System.out.println("try block: " + user);
            return user;
        } finally {
            user = new User("jj");
            return user;
        }
    }

    static class User {
        String name;
        User(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return hashCode() + ":"+ name;
        }
    }

执行结果:

try block: 780376:kk
29092282:jj

执行步骤 : 与场景3同

二、总结
1. 在try中return,在finally执行前会把结果保存起来,即使在finally中有修改也以try中保存的值为准,但如果是引用类型,修改的属性会以finally修改后的为准;
2. 如果try/finally都有return,直接返回finally中的return。
3. 不管try,finally都会执行;
4. 永远不要在finally块中使用return(PS: 提醒自己)

三、参考链接:
1. java中关于try、catch、finally的总结
2. Java趣味分享:try/finally

### Javatry-catch-finally执行顺序与异常处理机制 在Java中,`try-catch-finally` 是一种用于捕获和处理程序运行时异常的结构。其执行顺序和异常处理机制如下: #### 1. `try` 块 `try` 块包含可能抛出异常的代码。如果 `try` 块中的代码没有抛出异常,则会正常执行完该块内的所有语句[^1]。 #### 2. 异常抛出与 `catch` 块 如果 `try` 块中的代码抛出了异常,程序会立即停止执行 `try` 块剩余的部分,并跳转到与异常类型匹配的第一个 `catch` 块。如果没有匹配的 `catch` 块,则异常会被传递给调用栈中的上一层方法处理[^2]。 #### 3. `finally` 块 无论是否发生异常,`finally` 块中的代码都会被执行。即使在 `try` 或 `catch` 块中有 `return` 语句,`finally` 块仍然会在方法返回之前执行[^3]。 #### 执行顺序示例 以下代码展示了 `try-catch-finally` 的执行顺序: ```java public class TestTryCatchFinally { public static void main(String[] args) { System.out.println(test("12")); } public static int test(String str) { try { Integer.parseInt(str); // 可能抛出 NumberFormatException return 1; // 如果没有异常,返回1 } catch (NumberFormatException e) { return -1; // 捕获异常并返回-1 } finally { System.out.println("test结束"); // 无论是否有异常,都会执行 } } } ``` 在上述代码中,`finally` 块中的语句总是在 `try` 或 `catch` 块之后执行,即使 `try` 或 `catch` 块中有 `return` 语句[^3]。 #### 异常处理机制 Java中的异常处理基于“抓抛模型”。当程序运行过程中遇到异常时,会生成一个异常对象并将其提交给Java运行时系统。如果当前方法无法处理该异常,则会将异常传递给调用者方法,这一过程称为“抛出”异常。调用者方法可以选择捕获并处理异常,或者继续将异常向上层方法传递,直到异常被处理或导致程序终止。 #### 多重 `catch` 块 可以为同一种类型的异常提供多个 `catch` 块以实现不同的异常分类处理。例如: ```java public class MultiCatchExample { public static void main(String[] args) { try { int[] arr = {1, 2, 3}; System.out.println(arr[10]); // ArrayIndexOutOfBoundsException } catch (ArrayIndexOutOfBoundsException e) { System.out.println("数组越界异常:" + e.getMessage()); } catch (Exception e) { System.out.println("其他异常:" + e.getMessage()); } finally { System.out.println("finally执行"); } } } ``` 在此示例中,程序首先尝试访问数组的第11个元素(索引为10),这将抛出 `ArrayIndexOutOfBoundsException` 异常。由于第一个 `catch` 块能够处理该异常,因此不会进入第二个 `catch` 块[^4]。 ### 注意事项 - 如果 `try` 块中有 `return` 语句,`finally` 块仍会在方法返回之前执行。 - 如果 `try` 和 `catch` 块中都未处理某些异常,则这些异常会传播到调用栈的上层方法。 - `finally` 块通常用于释放资源(如关闭文件、数据库连接等)。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值