废话不多说,直接上代码:
public class test3 {
public static void main(String[] args) {
System.out.println(add());
}
public static int add() {
int i= 0;
try {
return i;
} finally {
i++;
}
}
}
结果为:0
分析一下代码:
1.当代码执行到return i;时,并不是直接将i返回了出去,而是将i保留了起来(因为还有一个finally语句块没有执行!)并且这个保留,就是值传递性质的一个保留,也就是保留的是i的一个副本(复制体),我这里先叫他ii吧.
2.接下来执行finally语句块,finally中将i做了自增运算,i的确变成了1,但是这并没有影响i的复制体ii的值!保留起来的ii的值还是0!
3.这个时候执行完了finally,正式将保留起来的ii返回出去,于是,整个函数的返回结果就是0
4.这个i的副本(复制体)保留的地方是哪儿呢?我查了半天,有个应该靠谱的说法,保留在函数栈中,但具体保留的区域叫什么,我也不知道,还请知情大佬指教一下!
上图或许直观一点:
那么如果,这个t是一个对象呢?按照前面说的值传递的问题,如果t是一个对象,在finally中对t进行修改,那么最终返回出去的t所显示出来的数据,应该是经过修改的。
写一个Person类来检验一下吧
public class Test {
public static void main(String[] args) {
Person result = test();
System.out.println(result.age);
}
public static Person test() {
Person t = new Person();
t.age = 0;
try {
return t;
} finally {
t.age++;
}
}
}
class Person {
int age;
}
这段代码输出的是1,因为Person是一个类,t是一个对象的引用,对象实例保存在堆内存中,t的副本tt也是一个对象的引用,t和tt都指向堆内存中的对象实例,那么不论修改谁,实际上对象实例都被修改了!
如果在finally中也有一个return,会发生什么?
public class test3 {
public static void main(String[] args) {
System.out.println(add());
}
public static int add() {
int i= 0;
try {
return i;
} finally {
i++;
return i;
}
}
}
结果为:1
就是说,如果try中有return而finally中也有return,那么后者将会让前者失效!
理解:try中将t保留了一份副本用于返回出去,到了finally中,又有一个return语句,这时候又要创建一个用于返回的副本,那这个时候就有两个副本了,到底返回谁呢?取后者!
总结:
java规范:finally比return先执行完毕。
也就是说,return先被执行了,执行return的时候发现有finally,于是不能那么快执行完毕return,先去执行finally,等finally执行完毕之后,return才能执行完毕。