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