首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Java的try-catch-finally问题分析

在日常编程中,我们经常遇到各种异常,比如NullPointerException、ClassNotFoundException、ArrayIndexOutOfBoundsException、ClassCastException、NumberFormatException等各种异常,因此,try-catch模块就成了我们代码的常客。如果try模块中所有语句正常执行完毕,那么finally块就会被执行;如果try模块在执行过程抛出异常,且无论异常是否可以被catch到,finally模块的代码都被执行到。但是就这样被我们每天都在使用的try-catch真的如我们想象的流程中走吗?今天我们就针对try-catch-finally中的一些细节问题分析一下。

方法1:

方法2:

对比上面两个方法,方法1的输出结果不难猜,直接输出“测试结果:finally”;但是方法2的输出结果可能出乎有些人的想象,输出“测试结果:try”,无需怀疑的是finally模块确实执行过的,那么为什么方法2会返回“try”呢,最有可能一种原因就是test方法在try模块return的时候,return是result的一份copy,然后随虽然正常执行了finally模块,修改了result的值,但是不会改变try模块的return值。

当然上面结果都是猜测,如何证明呢? 这里我们使用JBE(Java Bytecode Editor)工具(下载地址:http://set.ee/jbe/)查看一下方法2的字节码:

简单分析一下字节码命令,其中:

ldc:Push item from run-time constant pool,也就是把常量池变量推到栈顶,该命令负责把数值常量或String常量值从常量池中推送至栈顶,后面需要给一个表示常量在常量池中位置索引的参数;

astore_:Store reference into local variable,即将栈顶的objectref存入lvs,这里lvs表示局部标量表(local variable slot),其容量以变量槽(Variable Slot)为最小单位;

aload_:Load reference from local variable,从lvs读取一个objectref,存入栈顶;

areturn:Return reference from method,更加明确的说,是引用返回指令,代表返回栈顶的objectref。其它的返回指令还有ireturn(int)、lreturn(long)、dreturn(double)、freturn(float)和return(void)。

从字节码中我们可以看到,整个方法中只有两个return,我们只需分析到一个return即可,注意这里的栈都是指栈帧中的操作数栈:

将常量池中2号位置的字符串信息“try”推到栈顶;

将栈顶的内容“try”出栈并加载到局部变量表的0号Slot;

将局部变量表的0号Slot中的字符串“try”复制加载到栈顶;

将栈顶字符串内容“try”出栈并加载到局部变量表的1号Slot;

将常量中3号位置字符串“finally”推到栈顶;

将栈顶的内容“finally”出栈并加载到局部变量表的0号Slot;

将局部变量表中的1号Slot内容“try”复制到栈顶;

最后areturn结束方法执行,并将字符串引用“try”返回给方法调用者;

至此,我们的tes()方法调用结束了,虽然在finally模块中对result进行了赋值,但最终返回的确是“try”的一份赋值版本,所以后续大家需要注意一下return在try-catch-finally模块中到底如何使用,尽量在try-catch中使用return,避免出现一些自己想象不到的代码影响业务执行。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180310G0VFP000?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券