Java finally语句是在try或catch的retrurn之前还是之后执行

若try或catch中没有return语句,则按正常执行流,从上到下,finally里的所有修改都生效。

这里讨论的是try或catch里有return或throw语句的情形,此情形比较让人迷惑。

总结如下:

finally语句在try或catch的return或throw语句执行之后返回之前执行 且 finally里的语句不影响try或catch中已经确定的返回值(但能改变try或catch中引用对象里的成员,这跟final修饰的效果很像),除非finally里也有return或者throw等终止方法的语句,则就不会跳回try或catch执行,直接停止。

一般不建议在finally里return,在Eclipse里会警告 finally block does not complete normally

示例:

0、try中没有return语句,finally的修改生效

 1 class FinallyTest0 {
 2     public static void main(String[] args) {
 3         System.out.println(test0());
 4     }
 5 
 6     public static int test0() {
 7         int b = 20;
 8         try {
 9             System.out.println("try block");
10             
11             b += 80;
12         } catch (Exception e) {
13             b += 15;
14             System.out.println("catch block");
15         } finally {
16             System.out.println("finally block");
17             if (b > 25) {
18                 System.out.println("b>25, b = " + b);
19             }
20             b += 50;
21         }
22         return b;
23     }
24 }

执行结果:

try block
finally block
b>25, b = 100
150

此情形很简单,无须多言。当然,将return b;放在finally里的末尾效果也一样。

1、finally语句在try中return语句执行之后且返回之前执行的

 1 class FinallyTest1 {
 2     public static void main(String[] args) {
 3         System.out.println(test1());
 4     }
 5 
 6     public static int test1() {
 7         int b = 20;
 8         try {
 9             System.out.println("try block");
10             return b += 80;
11         } catch (Exception e) {
12             System.out.println("catch block");
13         } finally {
14             System.out.println("finally block");
15             if (b > 25) {
16                 System.out.println("b>25, b = " + b);
17             }
18         }
19         return b;
20     }
21 }

执行结果:

try block
finally block
b>25, b = 100
100

说明return语句已经执行了再去执行finally语句,不过并没有直接返回,而是等finally语句执行完了再返回结果。此外,从这也可以看出,程序执行完finally后就回到try中返回了,程序最后的return b并不会执行。

另一个示例:

 1 class FinallyTest1 {
 2     public static void main(String[] args) {
 3         System.out.println(test11());
 4     }
 5 
 6     public static String test11() {
 7         try {
 8             System.out.println("try block");
 9             return test12();
10         } finally {
11             System.out.println("finally block");
12         }
13     }
14 
15     public static String test12() {
16         System.out.println("return statement");
17         return "after return";
18     }
19 }

执行结果:

try block
return statement
finally block
after return

说明try中的return语句先执行了但并没有立即返回,等到finally执行结束后再返回。

2、finally块中的return语句会覆盖try块中的return返回

 1 class FinallyTest2 {
 2     public static void main(String[] args) {
 3         System.out.println(test2());
 4     }
 5 
 6     public static int test2() {
 7         int b = 20;
 8         try {
 9             System.out.println("try block");
10             return b += 80;
11         } catch (Exception e) {
12             System.out.println("catch block");
13         } finally {
14             System.out.println("finally block");
15             if (b > 25) {
16                 System.out.println("b>25, b = " + b);
17             }
18             return 200;
19         }
20         // return b;//不可达
21     }
22 }

执行结果:

try block
finally block
b>25, b = 100
200

说明finally里的return直接返回了,不管try中是否还有返回语句。

3、try中要返回的值不因finally里的修改而改变

 1 class FinallyTest3 {
 2     public static void main(String[] args) {
 3         System.out.println(test3());
 4     }
 5 
 6     public static int test3() {
 7         int b = 20;
 8         try {
 9             System.out.println("try block");
10             return b += 80;
11         } catch (Exception e) {
12             System.out.println("catch block");
13         } finally {
14             System.out.println("finally block");
15             if (b > 25) {
16                 System.out.println("b>25, b = " + b);
17             }
18             b = 150;
19         }
20         return 2000;
21     }
22 }

执行结果:

try block
finally block
b>25, b = 100
100

说明finally里的修改不改变try里的返回值。

 

另一个示例:(虽然对象的内容变了,但引用的是哪个对象并没变)

 1 class FinallyTest3 {
 2     public static void main(String[] args) {
 3         System.out.println(getMap().get("KEY").toString());
 4     }
 5 
 6     public static Map<String, String> getMap() {
 7         Map<String, String> map = new HashMap<String, String>();
 8         map.put("KEY", "INIT");
 9         try {
10             map.put("KEY", "TRY");
11             return map;
12         } catch (Exception e) {
13             map.put("KEY", "CATCH");
14         } finally {
15             map.put("KEY", "FINALLY");
16             map = null;
17         }
18         return map;
19     }
20 }

执行结果:

FINALLY

变量map是对象的引用,虽然finally中map.put使得引用的对象的内容变了,但对引用变量map的修改map=null并没对return的返回值起作用(返回值没变为null)。

注意体会 对引用的修改对引用对象的修改 两者的区别,这与final修饰一个引用变量的情形相似,虽然此时引用变量不可更改,但却可以修改引用对象里的内容。

 

如果把最后的 return map; 放到finally里末尾,则由上面的2知try里的return的值变了。示例如下:

 1 class FinallyTest3 {
 2     public static void main(String[] args) {
 3         System.out.println(getMap().get("KEY").toString());
 4     }
 5 
 6     public static Map<String, String> getMap() {
 7         Map<String, String> map = new HashMap<String, String>();
 8         map.put("KEY", "INIT");
 9         try {
10             map.put("KEY", "TRY");
11             return map;
12         } catch (Exception e) {
13             map.put("KEY", "CATCH");
14         } finally {
15             map.put("KEY", "FINALLY");
16             map = null;
17             return map;
18         }
19         // return map;
20     }
21 }
22 
23 结果:(由于try里返回了null,导致后续访问异常)
24 Exception in thread "main" java.lang.NullPointerException
25     at buaa.act.ucar.imtg.main.FinallyTest6.main(Test.java:23)

4、catch中的情形与try的一样

在try块发生异常的情况下其里面的return语句不会被执行,转到catch,catch里的执行情形与上述try的一样。

示例1及结果(对应0):

 1 class FinallyTest4 {
 2     public static void main(String[] args) {
 3         System.out.println(test4());
 4     }
 5 
 6     public static int test4() {
 7         int b = 20;
 8         try {
 9             System.out.println("try block");
10             b = b / 0;
11             return b += 80;
12         } catch (Exception e) {
13             b += 15;
14             System.out.println("catch block");
15         } finally {
16             System.out.println("finally block");
17             if (b > 25) {
18                 System.out.println("b>25, b = " + b);
19             }
20             b += 50;
21         }
22         return b;
23     }
24 }
try block
catch block
finally block
b>25, b = 35
85

在try里return之前发生了除0异常,所以try中的return不会被执行到,而是接着执行捕获异常的catch语句和最终的finally语句,此时两者对b的修改都影响了最终的返回值。

示例2及结果(对应1、3):

 1 class FinallyTest4 {
 2     public static void main(String[] args) {
 3         System.out.println(test4());
 4     }
 5 
 6     public static int test4() {
 7         int b = 20;
 8         try {
 9             System.out.println("try block");
10             b = b / 0;
11             return b += 80;
12         } catch (Exception e) {
13             System.out.println("catch block");
14             return b += 15;
15         } finally {
16             System.out.println("finally block");
17             if (b > 25) {
18                 System.out.println("b>25, b = " + b);
19             }
20             b += 50;
21         }
22     }
23 }
try block
catch block
finally block
b>25, b = 35
35

说明了发生异常后,catch中的return语句先执行,确定了返回值后再去执行finally块,执行完了catch再返回,finally里对b的改变对返回值无影响,原因同前面try的一样。

示例3及结果(对应2):在finally里末尾加上return b;则最后打印出的b值为85。

参考资料:http://www.cnblogs.com/lanxuezaipiao/p/3440471.html

原文地址:https://www.cnblogs.com/z-sm/p/6804071.html