先看一段代码:
@Test
public void test1(){
System.out.println(testf1());
}
int testf1()
{
int x = 1;
try
{
return x;
}
finally
{
++x;
System.out.println(x);
}
}
执行结果:----------------------------
2
1
为什么最后的返回结果不是2呢?明明finally已经对x+1的运行已经执行了才返回。
讲上面程序修改下,在finally块里也加上return。
@Test
public void test2(){
System.out.println(testf2());
}
int testf2()
{
int x = 1;
try
{
return x;
}
finally
{
++x;
System.out.println(x);
return x;
}
}
返回结果:------------------------
2
2
很奇怪,改完之后输出结果变成了2。
再将程序修改下:
@Test
public void test3(){
System.out.println(test8());
}
public int test8(){
try{
return f1();
}finally{
return f2();
}
}
public int f1(){
System.out.println("f1");
return 1;
}
public int f2(){
System.out.println("f2");
return 2;
}
执行结果:--------------------------
f1
f2
2
结果中可发现是在try块里的return语句先执行,但执行了return之后,子函数并没有立即返回,而是继续执行了finally块里的语句并return。最后的返回结果采取的是
finally块里的return结果。
猜想:子函数在try中return时将返回结果压入栈中,而在finally中再次return时,由于返回类型是基本类型,直接覆盖了上次的返回结果。这样子函数调用返回给上层函数的结果
就是最后一次finally中return的结果。为了验证这个猜想,继续修改程序,代码如下:
@Test
public void test9(){
StringBuilder sb = new StringBuilder("a");
System.out.println(test9(sb));
}
public StringBuilder test9(StringBuilder sb){
try{
return f1(sb);//先执行,将结果压入栈中
}finally{
return f2(sb);//后执行,再将前一次结果覆盖
}
}
private StringBuilder f2(StringBuilder sb) {
System.out.println("f2");
return sb.append("f2");
}
private StringBuilder f1(StringBuilder sb) {
System.out.println("f1");
return sb.append("f1");
}
f1
f2
af1f2
结果中也有try块中返回结果的f1,也有finally块中返回结果的f2。那为何与上次的实验结果不同呢,注意到这次返回类型是对象类型StringBuilder,每次return都是在原来的返回
结果上append,而不是覆盖。这也就验证了try中return子函数并没有实际返回,而是将结果存入到一个内存中,而finally中的return也是操作这块内存,如果是基本类型,则直
接覆盖,如果是引用类型,则根据具体的操作来决定是覆盖还是修改。