zoukankan      html  css  js  c++  java
  • Java语言中try-catch-finally的执行顺序

    try—catch—finally的使用

    原创 2017年06月20日 22:20:09

    例1:

    [java] view plain copy
     
    1. <span style="font-size:14px;">public static int func (){  
    2.     try{  
    3.         return 1;  
    4.     }catch (Exception e){  
    5.         return 2;  
    6.     }finally{  
    7.         return 3;  
    8.     }  
    9. }</span>  

    输出结果为:3

    例2:

    [java] view plain copy
     
    1. <span style="font-size:14px;">public class Test {  
    2.     public static void main(String[] args) {  
    3.        System.out.println(fun());  
    4.     }  
    5.     @SuppressWarnings("finally")  
    6.     public static int fun(){  
    7.         int  i = 0;  
    8.         try{  
    9.            return i;  
    10.        }catch(Exception e){  
    11.              
    12.            return ++i;  
    13.        }finally{     
    14.            ++i;  
    15.        }  
    16.     }  
    17. }</span>  

    虽然程序在执行return返回之前i的值已经变为1,但是输出结果为::0

    总结:

    return在try-catch-finally中:
    1、不管有木有出现异常,finally块中代码都会执行;
    2、当try和catch中有return时,finally仍然会执行;
    3、finally语句是在try或catch中的return语句执行之后返回之前执行的且finally里
    的修改语句不会影响try或catch
    中return已经确定的返回值
    (因为会把try或catch中return要返回的值先保存起来,
    然后再执行finally中的语句,
    所以不管finally中的代码怎么样,
    返回的值都不会改变,仍然是之前保存的值);
    若finally里也有return语句则覆盖try或catch中的return语句直接返回

    Java语言中try-catch-finally的执行顺序

    最近遇到一道Java编程题目,让根据以下程序写输出:

    [java] view plain copy
     
    1. public static int func (){  
    2.     try{  
    3.         return 1;  
    4.     }catch (Exception e){  
    5.         return 2;  
    6.     }finally{  
    7.         return 3;  
    8.     }  
    9. }  
    按着之前的想法,finally肯定会执行,但return这么多,猜想是编译错误,正确答案是3。遂在查找各种资料,找到了几处权威的,整理如下。

    -------------------分割线----------------

    finally的作用

    对于一些代码,无论try块中的异常是否会抛出,它们都得执行。这通常适用于内存回收之外的资源清理工作(内存回收由后台GC线程自动完成),如已经打开的文件或网络连接,屏幕上画的图形,数据库连接等等。那么这些代码就可以放到finally子句内。

    finally的使用

    finally正常的使用大家都比较常见,但在再次抛出异常、与return结合等情况下,容易产生迷惑,所以整理为下面几节。

    异常再次抛出时

    finally语句总会执行,甚至在异常没有被当前异常处理程序捕获,而重新抛出给更高一层前,finally会执行,例子是《Java编程思想》里的,如图:

    在return中使用finally

    由于finally总会执行,所以如果在return中使用finally,就可从多个点返回,同时保证重要的、必须的工作仍旧执行,即在含有finally的函数中,从何处返回无关紧要,示例如下:

    [java] view plain copy
     
    1. public class TryCatchFinally{  
    2.     public static int func(int i){  
    3.         System.out.println("func");  
    4.         try{  
    5.             System.out.println("try block");  
    6.             if(i == 1) return 1;  
    7.             if(i == 2) return 2;  
    8.             if(i == 3) return 3;  
    9.             return -1;  
    10.         }catch (Exception e){  
    11.             System.out.println("catch block");  
    12.             return -2;  
    13.         }finally{  
    14.             System.out.println("finally block");  
    15.         }  
    16.     }  
    17.       
    18.     public static void main(String[] args){   
    19.         for(int i=1; i <= 4; i++){  
    20.             System.out.println(func(i));  
    21.             System.out.println("-----------");  
    22.         }  
    23.     }  
    24. }  
    运行后输出内容为:
    [java] view plain copy
     
    1. func  
    2. try block  
    3. finally block  
    4. 1  
    5. -----------  
    6. func  
    7. try block  
    8. finally block  
    9. 2  
    10. -----------  
    11. func  
    12. try block  
    13. finally block  
    14. 3  
    15. -----------  
    16. func  
    17. try block  
    18. finally block  
    19. -1  
    20. -----------  
    注意:这里catch必须有返回值,否则报错。究其原因,是因为函数必须有返回值,如果try里面出错,try里的return就无效了,而finally、catch里都没有return,所以这两个字句必须至少有一个包含有返回值。

    finally的优先覆盖

    这里还需要指出,finally子句有最高的控制流返回权,其可以覆盖try、catch块内的任意Exception值、return值。如下的函数,将会返回12,而不是10。

    [java] view plain copy
     
    1. public static int getMonthsInYear(){  
    2.     try{  
    3.         return 10;  
    4.     } finally {  
    5.         return 12;  
    6.     }  
    7. }  
    同样地,如下函数,最后并不会抛出异常,而是返回值。
    [java] view plain copy
     
    1. public static int getMonthsInYear(){  
    2.     try{  
    3.         throw new RuntimeException();  
    4.     } finally {  
    5.         return 12;  
    6.     }  
    7. }  
    再对比这个函数,却抛出异常,并不返回值。
    [java] view plain copy
     
    1. public static int getMonthsInYear(){  
    2.     try{  
    3.         return 12;            
    4.     } finally {  
    5.         throw new RuntimeException();  
    6.     }  
    7. }  

    finally不执行的特殊情况

    finally子句一定会执行,除了极少的极端情况:

    • 调用了 System.exit() 
    • Java虚拟机崩了

    总结

    finally子句一定会执行,如果其含有程序控制流返回的语句,如return、throw e等,那么try、catch子句的相应控制流语句会失效;反之,当finally里没有控制流返回语句时,就会返回try或catch的控制流返回处,进行正常控制流交还操作。当然,这种编程方式是极不友好的,大概也只有在面试的时候能遇到吧。

    另外,参考里给的stachoverflow的链接里,有几个回答很好,比如有个牛人直接贴出了Java语言规范(JLS),有的一句话就点清,上面最后的三段代码就是参考的某个高票回答,想深入了解的请继续阅读探索。

  • 相关阅读:
    UVA 408 (13.07.28)
    linux概念之用户,组及权限
    Java实现 蓝桥杯 历届试题 网络寻路
    Java实现 蓝桥杯 历届试题 约数倍数选卡片
    Java实现 蓝桥杯 历届试题 约数倍数选卡片
    Java实现 蓝桥杯 历届试题 约数倍数选卡片
    Java实现 蓝桥杯 历届试题 约数倍数选卡片
    Java实现 蓝桥杯 历届试题 约数倍数选卡片
    Java实现 蓝桥杯 历届试题 九宫重排
    Java实现 蓝桥杯 历届试题 九宫重排
  • 原文地址:https://www.cnblogs.com/erma0-007/p/8644366.html
Copyright © 2011-2022 走看看