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),有的一句话就点清,上面最后的三段代码就是参考的某个高票回答,想深入了解的请继续阅读探索。

  • 相关阅读:
    vi使用方法详细介绍
    Jenkins实现Android自动化打包
    JSON知识总结
    React Native中pointerEvent属性
    从零学React Native之06flexbox布局
    Android Http实现文件的上传和下载
    从零学React Native之05混合开发
    React Native声明属性和属性确认
    从零学React Native之04自定义对话框
    Android 在图片的指定位置添加标记
  • 原文地址:https://www.cnblogs.com/erma0-007/p/8644366.html
Copyright © 2011-2022 走看看