java中的finally用法

笔试题
 java处理异常采用try-catch-finally语句捕获处理异常,finally常用来处理一些后续的工作,今天遇到了一个很容易错的知识点,我觉得有必要写点东西做一个总结。
 先提一下return语句的用法,return不管是在c/c++语言还是在java中都是返回函数值的语句。我们都知道return语句的一般作用:
  (1)给调用方返回一个值;
  (2)结束当前的方法(退出当前方法的调用栈)。
 并且当一个方法中有多个return时,会按照执行的顺序只执行第一个return,当然最终的函数返回值也是第一个return值。因为当执行第一个return语句后该方法就运行结束了。
 
那么问题来了:
请看下面的一个java的代码,读者也可先预想一下结果:

public class Test {
	public static void main(String[] args) {
		System.out.println(test(null) + "," + test("0") + "," + test(""));
	}

	public static int test(String str) {
		try {
			return str.charAt(0) - 48; //将字符转为数字,48是'0'的十进制数值
		} catch (NullPointerException e1) {
			return 1;
		} catch (StringIndexOutOfBoundsException e2) {
			return 2;
		} catch (Exception e3) {
			return 3;
		} finally {
			return 4;
		}
	}

答案是: 4,4,4
不知道你有没有做对,反正我是做错了,惭愧。
下面附上执行的结果(添加了异常信息的输出方法的结果,方便查看):

java.lang.NullPointerException
	at cn.test.example.Test.test(Test.java:14)
	at cn.test.example.Test.main(Test.java:9)
java.lang.StringIndexOutOfBoundsException: String index out of range: 0
	at java.lang.String.charAt(String.java:646)
	at cn.test.example.Test.test(Test.java:14)
	at cn.test.example.Test.main(Test.java:9)
4,4,4

输出结果分析:

  • (1) java中的finally语句首先在所有catch的后面,其次他是必须执行的,无条件执行的,即使前面的try-catch语句中已经存在异常了,它仍然会执行。
  • (2) 最然后不明白的就是当调用 tets(“null”)时会有NullPointerException类型的异常,但他还是会执行后面return 1;按照常理来说,运行到此处的return该方法就应该退出调用栈并且整个方法结束,但是看结果显示不是。
    那么,catch中的return语句有两种情况:
    • 运行了,但是没有让当前函数的调用结束:
    • 没有执行:这种推测有疑问就是,虚拟机的pc(程序计数器)是按顺序执行的,如果catch语句被执行,那么他内部的return语句也应该被执行,除非程序运行到catch语句就已经知道里面是return语句,但是这种运行方式需要提前知道我们是有写finally语句的
      一般遇到这样的问题,可能就不能停留在源码层面上了,得考虑考虑jvm对我们的程序做了什么,我们不如反编译一下class字节码,看看有什么特殊处理没,下面是我反编译的字节码代码:
public static int test(String str) {
       try {
           boolean var2;
           try {
               int var1 = str.charAt(0) - 48;
               return 4;
           } catch (NullPointerException var8) {
               var2 = true;
               return 4;
           } catch (StringIndexOutOfBoundsException var9) {
               var2 = true;
               return 4;
           } catch (Exception var10) {
               var2 = true;
               return 4;
           }
       } finally {
           ;
       }
   }

这下就能看出来了,原来jvm做了处理,finally中的return语句压根没被执行,三个catch语句中的return全都变成finally里面的return语句了,至于为什么这样做,等懂jvm编译原理的大佬来回答了。哈哈哈

  • 结论:
    • (1) 在try-catch-finally语句中,finally语句是必须执行的,
    • (2) 如果finally中有return语句,所有catch语句中的return语句将会被finally语句中的return语句代替,等价于finally语句中的return才是函数真正的return语句。

等价于变成下面这样代码

public static int test(String str) {
       int j;
       try {
           int i = str.charAt(0) - '0';
           return 4;
       } catch (NullPointerException e1) {
           e1 = e1;
           j = 1;
       } catch (StringIndexOutOfBoundsException e2) {
           e2 = e2;
           j = 2;
       } catch (Exception e3) {
           e3 = e3;
           j = 3;
       } finally {
       }
       return 4;
   }

虽然是个小问题,但是比较容易出错,所以在此作以说明。
转载请说明出处:http://blog.csdn.net/yyg_2015/article/details/52188066

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TechMix

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值