先来道题:
public class Test { public static void main(String[] args) { String result = getString(); System.out.println(result); } static String getString(){ String s1 = "1"; try { return s1; } finally { s1 = "3"; } }}
也许大家都知道在try中return之前都会先执行finally语句,结果应该是 “3”,但是输出的结果却是1。很奇怪是吧,这种问题只能看JVM虚拟机规范才知道,但是查资料比较麻烦,只能通过jvm指令看看虚拟机是如何做的。
执行 javap -c Test
static java.lang.String getString(); Code: 0: ldc #5 // String 1 2: astore_0 3: aload_0 4: astore_1 5: ldc #6 // String 3 7: astore_0 8: aload_1 9: areturn 10: astore_2 11: ldc #6 // String 3 13: astore_0 14: aload_2 15: athrow Exception table: from to target type 3 5 10 any 10 11 10 any
其中0-2行是将 "1"字符串赋值给第一个变量 3-4行 将第一个引用变量放入栈顶,然后将栈顶元素存入第二个变量(这个变量是虚拟机中的局部变量) 5-7行 存入"3" 进字符串常量池并将其推至栈顶,然后将栈顶元素存入第一个变量(s1),此时s1的值被改变了。 8-9行 载入第二个变量至栈顶,由于第二个变量的值是1(这里第二个变量是3-4行中对第一个变量的一个拷贝,第一个变量改变了,但是第二个变量的值还是保留) 最后将栈顶的值return,所以最后结果是 "1"
总结: 在java中,try中return的值是其拷贝(并非本身),finally对其修改,不会影响return的值。
思考: 如果将String s1 改成对象,在finally中修改对象属性会如何?