java中的finally关键字

finally关键字一般和try…catch…连用,一般不作妖的话(比如中途退出虚拟机等,这个不在讨论范围内,哈哈!),finally代码块是会执行的。

这篇博客主要讲一下有关finally的一些知识点。
话不多说,上例子↓

public class demo1 {
    public static void main(String[] args) {
        int i=0;
        try {
            i=10;
        }catch (Exception e){
            i=20;
        }finally {
            i=30;
        }
        System.out.println(i);
    }
}

显而易见,结果为30,反编译获取部分字节码

  		 0: iconst_0     
         1: istore_1
         2: bipush        10
         4: istore_1
         5: bipush        30
         7: istore_1
         8: goto          27
        11: astore_2
        12: bipush        20
        14: istore_1
        15: bipush        30
        17: istore_1
        18: goto          27
        21: astore_3 	//会利用一个没有名字的局部变量表中的槽位来存储异常对象
        22: bipush        30
        24: istore_1
        25: aload_3
        26: athrow
        27: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintSt
ream;
        30: iload_1
        31: invokevirtual #4                  // Method java/io/PrintStream.println:(I)V
        34: return
  
  Exception table:
        from    to  target type
          2     5    11   Class java/lang/Exception
          2     5    21   any #剩余的异常类型,比如error
          11    15   21   any

其中Exception table的内容相当于监视器,举个例子

from    to  target type
  2     5    11   Class java/lang/Exception

它监视[2,5)的字节码,一旦发生错误,则根据对应的错误类型跳转到不同的地方,假如[2,5)的地方发生了Exception类的错误,则跳转到11: astore_2,如果发生了其他的比如error错误,则跳转到21: astore_3,然后往下执行,

最后26: athrow抛出异常!!(第三个例子不抛出异常)

总结:

  • 从字节码可以看到finally中的代码被复制了3份,分别放入try流程,catch流程,以及catch剩余的异常类型流程

第二个例子:

public static void main(String[] args) {
        int result=test();
        System.out.println(result);
    }
    public static int test(){
        try {
            return 10;
        }finally {
            return 20;
        }
    }

test部分的字节码

public static int test();
    descriptor: ()I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=2, args_size=0
         0: bipush        10  //10放入栈顶
         2: istore_0		 //10-> slot 0 (从栈顶移除了)
         3: bipush        20 //20放入栈顶
         5: ireturn			 //返回栈顶 int(20)
         6: astore_1		//catch any -> slot 1
         7: bipush        20//20 放入栈顶
         9: ireturn			//返回栈顶 int(20)
      Exception table:
         from    to  target type
           0     3     6   any

所以结果为20.

总结:

  • 由于finally中的ireturn被插入了所有可能的流程,因此返回结果肯定以finally的为准

第三个例子

public static void main(String[] args) {
        int result=test();
        System.out.println(result);
    }
    public static int test(){
        try {
            int i=1/0;
            return 10;
        }finally {
            return 20;
        }
    }

它的输出结果为20,不会抛出异常。字节码如下:

public static int test();
    descriptor: ()I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=0
         0: iconst_1
         1: iconst_0
         2: idiv
         3: istore_0
         4: bipush        10
         6: istore_1
         7: bipush        20
         9: ireturn
        10: astore_2
        11: bipush        20
        13: ireturn
      Exception table:
         from    to  target type
           0     7    10   any

总结:

  • 跟第一个例子相比,没有athrow,这告诉我们:如果在finally中出现了return,会吞掉异常。

第四个例子

public static void main(String[] args) {
        int result=test();
        System.out.println(result);
    }
    public static int test(){
        int i=10;
        try {
            return i;
        }finally {
            i=20;
        }
    }

结果为10,理由看字节码:

public static int test();
    descriptor: ()I
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=3, args_size=0
         0: bipush        10  #10 放入栈顶
         2: istore_0 #10->i
         3: iload_0			
         4: istore_1 #暂存到slot 1,目的是为了固定返回值
         5: bipush        20
         7: istore_0
         8: iload_1
         9: ireturn
        10: astore_2
        11: bipush        20
        13: istore_0
        14: aload_2
        15: athrow
      Exception table:
         from    to  target type
           3     5    10   any

有错误的话望指正
本文章参考:黑马程序员JVM.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值