背景

在java编程过程中,经常会使用 try catch语句来处理异常,对打开了资源的文件的,要使用finally进行关闭。 正常的执行顺序是 try块,如果没有异常执行finally块,有异常跳转到catch块,最后执行finally块。 刚好遇到一个try catch 带有finally的语句,还使用了return。于是,就想到了语句执行情况的问题。

验证

编程,哪里不清楚,运行一下不就好了。交代一下运行环境,操作系统是 Windows7 64位,使用的java环境是java 1.8.0_66。

类的基本定义

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21

public class TryCachTest {
    // catch 工作
    public static String catchMethod() {
        System.out.println("catchMethod is running ==1==");
        return "catch method";
    }

    // finally工作
    public static String finallyMethod() {
        System.out.println("finallyMethod is running ==2==");
        return "finally method";
    }

    // return 工作
    public static String returnMethod(String methodName){
        System.out.println( methodName + " call returnMethod is running ==3==");
        return "=" + methodName;
    }
}

正常抛出异常,没有finally, try块、catch块均有return 执行情况

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
    public static String catchTest() {
        System.out.println("====catchTest=====");
        try {
            int i = 10 / 0;   // 抛出 Exception,后续处理被拒绝
            System.out.println("i vaule is : " + i);
            return returnMethod("catchTest");    // Exception 已经抛出,没有获得被执行的机会
        } catch (Exception e) {
            System.out.println(" -- Exception --");
            return catchMethod();    // Exception 抛出,获得了调用方法并返回方法值的机会
        }
    }

    public static void main(String[] args) {
        System.out.println(catchTest());
    }

输出为

====catchTest===== – Exception – catchMethod is running ==1== catch method

说明: 在try块中,遇到异常,异常之后的语句没有机会执行。try抛出异常后执行catch块内容

正常抛出异常,有finally,try块、catch块有return,finally无return 执行情况

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
    public static String catchFinallyTest1() {
        System.out.println("=========");
        System.out.println("catchFinallyTest1");
        try {
            int i = 10 / 0; // 抛出 Exception,后续处理被拒绝
            System.out.println("i vaule is : " + i);    // Exception 已经抛出,没有获得被执行的机会
            return returnMethod("catchFinallyTest1");   
        } catch (Exception e) {
            System.out.println(" -- Exception --");
            return catchMethod();  // Exception 抛出,获得了调用方法的机会,但方法值在 finally 执行完后才返回
        } finally {
            finallyMethod();  // Exception 抛出,finally 代码块将在 catch 执行 return 之前被执行
        }
    }

    public static void main(String[] args) {
        System.out.println(catchFinallyTest1());
    }

输出为:

========= catchFinallyTest1 – Exception – catchMethod is running ==1== finallyMethod is running ==2== catch method

说明: 在try块中,遇到异常,异常之后的语句没有机会执行。try抛出异常后执行catch块内容,直到catch块执行到 return 语句之前(return关键字参数也会执行),跳转执行finally。等finally执行完后再返回 catch的return值。

不抛出异常,有finally,try块、catch块有return,finally无return 执行情况

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
   public static String catchFinallyTest2() {
       System.out.println("=========");
       System.out.println("catchFinallyTest2");
       try {
           int i = 10 / 2; // 不抛出 Exception
           System.out.println("i vaule is : " + i);
           return returnMethod("catchFinallyTest2");
       } catch (Exception e) {
           System.out.println(" -- Exception --");
           return catchMethod();  // 不抛出 Exception ,没有获得被执行的机会
       } finally {
           finallyMethod();  // 不抛出 Exception ,finally 代码块将在 try 执行 return 之前被执行
       }
   }

   public static void main(String[] args) {
       System.out.println(catchFinallyTest2());
   }

输出为:

========= catchFinallyTest2 i vaule is : 5 catchFinallyTest2 call returnMethod is running ==3== finallyMethod is running ==2== =catchFinallyTest2

说明: 在try块中,没有遇到异常,try块会执行到return之前(return关键字参数也会执行),跳转到finally执行,最后执行返回 try块中的返回值。

若 finally中包含有 return

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    public static String catchFinallyTest3() {
        System.out.println("=========");
        System.out.println("catchFinallyTest3");
        try {
            int i = 10 / 2;  // 不抛出 Exception
            System.out.println("i vaule is : " + i);
            return returnMethod("catchFinallyTest3");   // 获得被执行的机会,但执行需要在 finally 执行完成之后才能被执行
        } catch (Exception e) {
            System.out.println(" -- Exception --");
            return catchMethod();
        } finally {
            return finallyMethod();  // finally 中含有 return 语句,这个 return 将结束这个方法,不会在执行完之后再跳回 try 或 catch 继续执行,方法到此结束,返回 false
        }
    }

    public static String catchFinallyTest4() {
        System.out.println("=========");
        System.out.println("catchFinallyTest4");
        try {
            int i = 10 / 0;  // 抛出 Exception,后续处理被拒绝
            System.out.println("i vaule is : " + i);    // Exception 已经抛出,没有获得被执行的机会
            return returnMethod("catchFinallyTest4");
        } catch (Exception e) {
            System.out.println(" -- Exception --");
            return catchMethod();
        } finally {
            return finallyMethod();     // finally 中含有 return 语句,这个 return 将结束这个方法,不会在执行完之后再跳回 try 或 catch 继续执行,方法到此结束,返回 false
        }
    }

    public static void main(String[] args) {
        System.out.println(catchFinallyTest3());
        System.out.println(catchFinallyTest4());
    }

输出为:

========= catchFinallyTest3 i vaule is : 5 catchFinallyTest3 call returnMethod is running ==3== finallyMethod is running ==2== finally method

catchFinallyTest4 – Exception – catchMethod is running ==1== finallyMethod is running ==2== finally method

说明: 若try、catch、finally块中都包含有 return 关键字,最后返回的值是 finally 块中的值。该执行的 return 关键字参数语句会执行

若try或catch块中包含有exit()方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
    public static String catchFinallyTest5() {
        System.out.println("=========");
        System.out.println("catchFinallyTest5");
        try {
            int i = 10 / 2;  // 不抛出 Exception
            System.out.println("i vaule is : " + i);
            System.exit(0);
        } catch (Exception e) {
            System.out.println(" -- Exception --");
            return catchMethod();
        } finally {
            return finallyMethod();  // finally 中含有 return 语句,这个 return 将结束这个方法,不会在执行完之后再跳回 try 或 catch 继续执行,方法到此结束,返回 false
        }
    }

    public static void main(String[] args) {
        System.out.println(catchFinallyTest5());
    }

输出为:

========= catchFinallyTest5 i vaule is : 5

说明: 若try(catch)块下包含有exit()方法,执行到exit()方法时,程序直接退出,不会做其他的清理工作。

总结

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
st=>start: 开始
e=>end: 结束
op1=>operation: 进入Try代码块
op11=>operation: 执行到Try代码块的
Return前(包含Return参数)
op12=>operation: Return Try块的返回参数
op2=>operation: 进入Catch代码块并执行到
Return前(包含Return参数)
op21=>operation: Return Catch块的返回参数
op3=>operation: 进入Finally代码块并执行到
op30=>operation: 进入Finally代码块并执行到
Return前(包含Return参数)
op31=>operation: Return Finally块的返回参数

cond1=>condition: 是否抛
出异常
cond2=>condition: 是否包含
Finally块
cond3=>condition: Finally块是
否包含Return

cond21=>condition: 是否包含
Finally块
cond31=>condition: Finally块是
否包含Return

st->op1->cond1
cond1(yes)->op2->cond2
cond1(no)->op11->cond21
cond2(yes)->op3->cond3
cond3(yes)->op31
cond3(no)->op21
cond2(np)->op21
cond21(yes)->op30->cond31
cond21(no)->op12
cond31(yes)->op31
cond31(no)->op12
op12->e
op21->e
op31->e