深入学习try-catch-finally以及各个代码块有无返回值的区别

一、try-catch

说明:在出现try-catch代码块的情况,会先进入try代码块,然后监控整个try中的代码,如果出现异常就会catch代码块中。

实例代码:

      int i = 0;
        try {
            i = 10;
        } catch (Exception e) {
            i = 20;
        }

对应字节码:

  •  首先是第0-1行,对应的就是int i= 0 ,将0存入本地变量1号槽位
  • 2-5行对应着cry中的代码,先将10压入操作数栈,然后将操作数栈中的10存放到本地变量1号槽位,如果期间没有出现异常就执行第5行的goto,找到第12行return结束                            这时候看红框框出的部分,表示监控着2-5行,不包括第5行,如果期间出现异常,就会匹配异常,如果和我们catch中的异常一致那么就不走第5行,而是接着进入第8行
  • 8-11行表示进入catch块中,第八行表示将Exception放入本地变量2号槽位,9-11表示将20赋值给1本地变量1号槽位i
  • 12行return结束

二、多个single-catch块的情况

说明:会先进入try代码块中执行,如果在try中出现了异常,这时候会对异常类型进行判断,根据正确或者说更精细的异常匹配到相应的catch块入口

实例代码:

public class Demo3_11_2 {
    public static void main(String[] args) {
        int i = 0;
        try {
                    i = 10;
        } catch (ArithmeticException e) {
            i = 30;
        } catch (NullPointerException e) {
            i = 40;
        } catch (Exception e) {
            i = 50;
        }
    }
}

对应字节码:

  •  首先是第0-1行,对应的就是int i= 0 ,将0存入本地变量1号槽位
  • 2-5行对应着cry中的代码,先将10压入操作数栈,然后将操作数栈中的10存放到本地变量1号槽位,如果期间没有出现异常就执行第5行的goto,找到第12行return结束                                
  • 如果期间出现了异常,就会根据第一个红框中的异常监控,找到匹配的异常,然后根据target找到下一行的入口,例如,如果是NullPointerException异常,那么就会跳到15行
  • 15-19行表示出现NullPointerException后执行对应的catch块代码,当执行完后就会执行第19行goto,然后找到26行return结束
  • 在整个过程中用于存储异常的本地变量槽位只有一个二号槽位,使用的是槽位复用,减少不必要的开销

try-catch-finally

说明:会先进入try代码块,如果期间出现异常就会进入catch块,当catch块执行完后进入finally块。如果期间没有出现异常,执行完try块之后就会进入finally块。也就是finally是最终必执行的代码块

实例代码:

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

对应字节码

  •  首先是第0-1行,对应的就是int i= 0 ,将0存入本地变量1号槽位
  •  2-4行对应着cry中的代码,先将10压入操作数栈,然后将操作数栈中的10存放到本地变量1号槽位如果期间没有出现问题那么就会接着执行5-8行,这几行实际是finaly中的指令                   -如果期间出现了异常,先来看一下4号红框中的内容,第三行中的 2  5  11 Class java/lang/Exception 会监控2-5行号的代码,不包括第五行,也就是try块中的指令,如果发生了异常时Exception类型的 那么就会进入第11行
  • 11-14行就是catch块中的内容,将30赋值给i,如果期间没有出现问题,那么就会接着执行15-18行,这几行实际时finally中的指令                                                                                                      如果期间出现了异常,再来看一下4号红框中的内容,第四行2 5 21 any 代表的意思时,监控2-5行号的代码,不包括第五行,也就是try块中的指令,如果发生了异常,但是异常的类型并不是我们指定catch中的接收的异常类型,那么就会进入21行号的代码,也就是finally块,第五行11 15 21 any 代表的是监控着11-15行的代码,不包括15行,也就是监控catch块中的代码,如果再次出现了异常,那么就进入21行,也就是finally块中的指令
  • 21-26中就表示try发生异常但是catch中无法接收异常或者catch中发生异常的情况,将发生的异常放入本地变量表3号槽位,然后执行finally中的指令,26行将异常抛出,执行完毕后就return结束
  • 也就是说虚拟机在编译的时候会将finally中的内容复制三分,一份放在try的末尾,一份放在catch的末尾,一份放在finally的位置,并且如果try发生了异常,在catch中进行处理,可以不抛出异常,但是再finally中进行处理,一定会抛出异常,除非finally中有return

try-finally try中有return,finally中没有return

说明:会先执行try中的指令,当执行到return前,会先将finaly中的指令执行完毕后再执行try中的return

实例代码:

public class Demo3_12_2 {
    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;
        }
    }
}

对应字节码:

  • 0-2行中执行的是try之前的代码 ,将10压入栈顶后存入本地变量表0号槽位
  • 3-4行在return i 之前,因为还有finally的代码块没执行,先将本地变量表0号槽位的值压入栈顶中,然后又将值保留到本地变量表1号槽位,为了保证返回值就是10。
  • 而5-7行则执行的是finally的内容,先将20压入栈顶,然后存入本地变量表0号槽位,也就是i
  • 8-9行 当finally的内容执行完了之后,就会将try块return之前的i的值从本地变量表1号槽位中取出来,压入栈顶,然后返回。
  • 红框的内容表示,会监控3-5行的指令,不包括第五行,如果期间出现异常那么就会进入第10行号指令,也就是finally块的内容
  • 10-15  整个finally要做的事情
  • 第10行表示将异常类型存入本地变量表的2号槽位
  • 11-13行 用户显示的在finally块中输入的内容,将20压入栈顶,然后保存到本地变量表0号槽位
  • 14行将本地变量表2号槽位载入操作数栈中,也就是异常
  • 15行抛出异常

try-finally  try中有return finally中也有return

说明:会先执行try中的指令,当执行到return 的时候,会跳过return,继续执行finally中的内容

实例代码:

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

    public static int test() {
        try {
            return 10;
        } finally {
            return 20;
        }
    }

对应字节码:

0行指令将10压入栈顶,在第二行中又将10从栈顶移除,然后执行finaly中的内容,先将20压入栈顶,然后返回栈顶内容。整个过程中监控0-3行,不包括第3行号,如果出现了异常就会直接进入第六行,将异常类型存入本地变量表1号槽位,然后开始执行finally的代码,值得注意的是当finally中有返回值的时候,会吞掉异常,直接返回。这样我们根本不知道程序出现了异常

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值