finally语句块

作者: 我是许同学 | 来源:发表于2017-04-19 20:13 被阅读90次

    finally语句块与return

    运行下面的代码,想想在程序正常运行时输出什么,出现异常时输出什么?

    public class Test {
        public static void main(String[] args) {
            System.out.println("return value of test() : " + test());
        }
    
         public static int test() {
             int x;
            try {
                x = 1;
                return x;
            } catch (Exception e) {
                x = 2;
                return x;
            } finally {
                x = 3;
            }
        }
    }
    

    运行上面的代码,在test()方法正常运行时返回1,出现异常时返回2;可能和你想的不太一样。在下面,使用javap -v 查看java在字节码层面对test()方法的实现:

    public static int test();
        descriptor: ()I
        flags: ACC_PUBLIC, ACC_STATIC
        Code:
          stack=1, locals=4, args_size=0
             0: iconst_1
             1: istore_0
             2: iload_0
             3: istore_1
             4: iconst_3
             5: istore_0
             6: iload_1
             7: ireturn
             8: astore_1
             9: iconst_2
            10: istore_0
            11: iload_0
            12: istore_2
            13: iconst_3
            14: istore_0
            15: iload_2
            16: ireturn
            17: astore_3
            18: iconst_3
            19: istore_0
            20: aload_3
            21: athrow
          Exception table:
             from    to  target type
                 0     4     8   Class java/lang/Exception
                 0     4    17   any
                 8    13    17   any
    

    如果test方法执行中没有发生异常:

    0:1 入栈
    1:1 出栈存入Slot0 中
    2:装载slot0 中的 1 入栈
    3:1 出栈存入Slot1 中
    4: 3 入栈
    5: 3 出栈存入Slot0中
    6: 装载slot1中 1 入栈
    7: 返回栈顶元素 1 , 方法结束

    如果test方法在执行0 ~ 4(不包含第4条) 条字节码指令时发生Exception异常,跳转到第8条指令开始执行:

    8: 把栈顶异常存入Slot1
    9: 2 入栈
    10:2 出栈存入 Slot0
    11: 装载Slot0中的 2 入栈
    12:2 出栈存入 Slot2
    13:3 入栈
    14:3 出栈存入Slot0
    15:装载Slot2中 2 入栈
    16:返回栈顶元素2 ,返回结束

    如果发生Exception以外的异常跳到第17条指令执行,方法非正常退出,无返回值。

    无论程序在运行中,发生不发生Exception异常,在执行i = 3 前,总会复制 i 的值到最后一个本地变量表的Slot 中(暂时把这个Slot称为returnValue),在执行ireturn前,总会把returnValue压入栈顶,作为方法返回值使用。

    finally语句块什么时候执行?

    由上面问题中的字节码指令可以看出:无论有无异常发生,finally语句块在try 和 catch 语句 return之前执行。

     public class Test { 
     public static void main(String[] args) { 
            System.out.println("return value of getValue(): " + getValue()); 
         } 
    
     public static int getValue() { 
            try { 
                     return 0; 
            } finally { 
                     return 1; 
                } 
         } 
     }
    

    所以下面代码的执行结果为: return value of getValue(): 1

    finally 块中的 return 返回后方法结束执行,不会再执行 try 块中的 return 语句。《阿里巴巴Java开发手册》中【强制】不能在 finally 块中使用 return。


    相关文章

      网友评论

        本文标题:finally语句块

        本文链接:https://www.haomeiwen.com/subject/ebpxpttx.html