欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

try-catch-finally

程序员文章站 2022-04-06 15:54:43
...

一. 先看结论

当Java程序执行try块、catch块遇到return语句时,系统执行完return语句之后,并不会立即结束该方法,而是去寻找该异常处理流程中是否包含finally块,如果没有finally块,方法终止,返回相应的返回值。如果有finally块,系统立即开始执行finally块——只有当finally块执行完成后,系统才会再次跳回来根据return语句结束方法。如果finally块里使用了return语句来导致方法结束,则finally块已经结束了方法,系统不会跳回去执行try、catch块里的任何代。

二.实际情况分析

情况1:try{} catch(){}finally{} return; 显然程序按顺序执行。

情况2: try{ return; }catch(){} finally{} return; 程序执行try块中return之前(包括return语句中的表达式运算)代码; 再执行finally块,最后执行try中return; finally块之后的语句return,因为程序在try中已经return所以不再执行。

情况3:try{ } catch(){return;} finally{} return; 程序先执行try,如果遇到异常执行catch块, 有异常:则执行catch中return之前(包括return语句中的表达式运算)代码,再执行finally语句中全部代码, 最后执行catch块中return. finally之后也就是4处的代码不再执行。 无异常:执行完try再finally再return.

情况4:try{ return; }catch(){} finally{return;} 程序执行try块中return之前(包括return语句中的表达式运算)代码; 再执行finally块,因为finally块中有return所以提前退出。

情况5:try{} catch(){return;}finally{return;} 程序执行catch块中return之前(包括return语句中的表达式运算)代码; 再执行finally块,因为finally块中有return所以提前退出。

情况6:try{ return;}catch(){return;} finally{return;} 程序执行try块中return之前(包括return语句中的表达式运算)代码; 有异常:执行catch块中return之前(包括return语句中的表达式运算)代码; 则再执行finally块,因为finally块中有return所以提前退出。 无异常:则再执行finally块,因为finally块中有return所以提前退出。

三.捉到几只Sample

1)Sample1

public class Test {
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println("返回结果:"+t.go());
    }

    public int go() {
        int a = 1;
        try {
            int i = 1 / 0;  //这里会有异常
            System.out.println("go方法里面:a1 = " + a);
            return a;
        } catch (Exception e) {
            System.out.println("go方法里面:a2 = " + a);
            return a;
        } finally {
            a++;
            System.out.println("go方法里面:a3 = " + a);
        }
    }
}
输出结果:

go方法里面: a2 = 1
go方法里面: a3 = 2
返回结果: 1
注意:这里主要注意的是,在finally里面a变量的值虽然已经变为2,但是由于return语句在catch里面已经执行过了,所以最终的返回值不会改变

2)Sample2


public class Test {
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println("返回结果:"+t.go());
    }

    public int go() {
        int a = 1;
        try {
            int i = 1 / 0;  //这里会有异常
            System.out.println("go方法里面:a1 = " + a);
            return a;
        } catch (Exception e) {
            System.out.println("go方法里面:a2 = " + a);
            return a;
        } finally {
          return 6;
        }
    }
}
输出结果:

go方法里面: a2 = 1
返回结果: 6
注意:这里主要注意的是,在catch里面虽然执行了return 1(a的值是1),但是程序并没有立马返回,
而是进入finally,finally里面有一个return 6,程序执行return 6覆盖掉了之前的return 1并返回。

3)Sample3 (如果你的答案与下面一样,那你的理解已经很到位了)


public class Test {
    public static void main(String[] args) {
        Test t = new Test();
        try{
            System.out.println("返回结果:"+t.go());
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("执行结束");
    }

    public int go() throws Exception{
        int a = 1;
        try {
            throw new RuntimeException("错误1");
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("错误2");
        } finally {
        return 2;
        }
    }
}

输出结果:

java.lang.RuntimeException: 错误1
返回结果:2
执行结束
注意:这里主要注意的是,在try里面throw一个异常会被catch捉住,并不会向上抛。
      但是在catch里面throw一个异常(throw new RuntimeException("错误2")),如果不重新try的话,
      就需要向上抛了,但是在抛之前程序会先执行finally里面的代码,在这个sample中,finally里面
      的return把本来要抛出的异常给覆盖掉了,所以 System.out.println("返回结果:"+t.go())并没有捕获到异常。