1、前言
今天同事给我看了一段代码,然后这段简单的代码,我却陷入了沉思。
2、代码
String string = ""; try { string = "123"; return string; } finally { string = "234"; }
这段代码,string最终是“123”还是“234”呢?按照以往认知:finally快是如论如何都要执行的,而return会等待finally执行结束后返回,这里string被修改为"234",那么return的值也就是"234"。
如果你也是这么想的,那么恭喜你,你也错了。
我们来看下chatGPT怎么说的:
正如chatGPT所说的,确实如此。这里吐槽以下,文某某言返回的居然是“234”???
我们用IDEA执行下这段代码:
甚至我们可以看到,idea在finally里面的赋值给出了提示。 提示该string的赋值是不会被使用的。
而执行结果也正是123。
那么既然结果如此,那么真相是什么呢?
3、return和finally
其实finally始终都会执行是没错的!!! 我们先来看下该方法的字节码:
我们可以看到当执行到return时,此时string=123,jvm会将此时的变量地址存储到栈中,当finally执行了string=234后,只是改变了堆对象的值,而方法返回的该变量的地址。此时finally虽然改变了值,但是地址没有被改变,因此返回的还是原地址所执行的值。
4、改变一下
String string = ""; try { string = "123"; return string; } finally { string = "234"; return string; }
那如果是这段呢?finally中也加了return。我们再来看下字节码:
与上面不同的是,这里多了个areturn,也就是是这里的finally最终的返回会将该变量的地址推到栈顶位置,也就改变了原string=123的值,所以string就会输出234了。
5、小结
好了,又一个无聊又有趣的小知识。如果这个会出错的,大多还是对于jvm以及基础不够扎实的缘故。这里我也检讨一下。还是要学会看字节码的习惯,这里字节码是不会骗人的。