首先我们来看题
当做这道题时我的答案是“ABAA”。因为先执行try得到A然后执行finally 得到B 再回到try 中的return 得到A 再输出个A。但是当我看答案的时候不是这样的
正确答案是ABAB
因此得到一个结论
finally语句块在return语句之后,return返回值之前
看下一个例子
运行结果
由此我们可知 输出了try之后 运行了b=b+80 但是没有返回 就去执行finally 等到finally执行完以后才返回结果
例子二
执行结果
由结果可得 先执行了try 然后运行了test4,输出了return statement 返回值没有返回 去执行finally 然后返回after return
那么问题来了,如果 finally中对return的值进行修改,那么return返回来的值是修改前的还是修改后的
例子三
执行结果
可以看到没什么变化 那么我们可以得到一个结论
finally中对return的值进行了修改之后 并不会影响try中return的返回值
其实这样是不太对的 因为我们只验证了基本类型 那么下面我们验证一下引用类型来证明我们的结论是否正确
例子四
执行结果
由此看来基本类型和引用类型的结论是不同的
那么让我们总结一下吧
对于基本数据类型,finally语句块中对try语句块的return的变量进行了修改,return的则是修改前的值。
对于引用数据类型,finally语句块中对try语句块的return的变量进行了修改,return的则是修改后的值。
看到这里,不知道你有没有想到这个结论与 Java 的方法调用时的所谓的值传递和引用传递的结论有些类似。
既然得出了这个结论,那么这个结论是必然的情况么?一定正确么?别急,来看下一个例子。
例子五
执行结果
看到这个结果是不是很震惊 为什么 推翻了上面的结论 到底是为什么呐
先说基本数据类型,由于基本数据类型是 值传递 ,所以在try里的return执行的时候,就先将变量的值隐性的作为最终返回的值。
同样的,对于引用数据类型,只是将该变量所指向的内存地址隐性的作为最终返回的值,所以即使将stu = null,也无所谓了,因为早在执行finally之前,try里的return就已经拿到了stu所指向的地址。
这里多说一句,其实 Java 里都是值传递,只不过基本数据类型的值是真正的值,而引用数据类型是地址值而已。
思考题
问:如果try与finally中都有return语句,那么到底会返回哪一个呢?
会返回finally中的return。
问:如果try里有return语句,整个try-catch-finally块之外也有一个return语句,那么哪个会执行,一定是这样么?
在try里没有发生异常的情况下,是try里的return会执行,但发生了异常,则反之。
问:如果catch中有return语句呢?当然只有在异常的情况下才有可能会执行,那么是在finally之前就返回吗?
当发生异常后,catch中的return执行情况与未发生异常时try中return的执行情况完全一样。
总结
finally 块的语句在 try 或 catch 中的 return 语句执行之后返回之前执行,且 finally 里的修改语句可能影响也可能不影响 try 或 catch 中 return 已经确定的返回值,若 finally 里也有 return 语句则覆盖 try 或 catch 中的 return 语句直接返回。
PS:本篇文章参考了一些别人的博客和观点