zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    JAVA与.NET的相互调用——通过Web服务实现相互调用
    WCF大数据量传输配置
    WCF大数据量传输解决方案
    C# #if DEBUG
    我对CSS vertical-align的一些理解与认识(一)
    htmlparser使用例子(全) 转载
    【HtmlParser】HtmlParser使用
    HTMLParser 使用详解
    htmlparser源码简单分析
    利用OpenXml生成Word2007文档
  • 原文地址:https://www.cnblogs.com/z-sm/p/6804071.html
Copyright © 2011-2022 走看看