首先来看一个程序(finally块中有return)
public static int test(){
int i = 0;
try{
i = 1;
System.out.println("try i= "+i);
return i;
}catch (Exception e){
i = 2;
return i;
}finally {
i = 3;
System.out.println("finally i= "+i);
return i;
}
}
运行结果是
try i= 1
finally i= 3
3
我们打上断点看一下 i 的变化过程
- 第一步是在 try 中, return时 i : 1
- 由于这个程序没有出现异常, catch中的代码块不执行
- 进入到 finally 中, 此时 输出和return都发生了变化 , i 变成了 3
- test输出的结果3
结论: 此时test方法的返回值是3, 在try, catch中的返回值被finally的返回值给屏蔽掉了, 所以如果finally中有return则会屏蔽方法中的返回值
再来看一个程序(finally中无return)
public static int test1(){
int i = 0;
try{
i = 1;
System.out.println("try i="+i);
return i;
}catch (Exception e){
i = 2;
return i;
}finally {
i = 3;
System.out.println("finally i="+i);
}
}
运行结果是
try i= 1
finally i= 3
1
同样打上断点看一下变化过程
- 第一步还是在try中, 这时 i 是 1, return 的结果是 i : 1
- 程序中没有出现异常, catch中的代码块不会执行
- 进入到finally中, i 受到了影响, 值改变了, 变成了3
- test输出的结果仍然是1
结论: 根据结果可以看到方法test的返回值不受finally中的影响, 但是变量i还是受到了影响, 它的值改变了, 返回值是放在栈中的, return就是把返回值压栈了, 相当于一个临时变量, 在finally中并不会影响返回值
再看一个程序 (finally中有return)
public static ExceptionTest test2(){
ExceptionTest exceptionTest = new ExceptionTest();
try{
exceptionTest.age = 1;
System.out.println("try age= "+exceptionTest.age);
return exceptionTest;
}catch (Exception e){
exceptionTest.age = 2;
return exceptionTest;
}finally {
exceptionTest.age = 3;
System.out.println("finally age= "+exceptionTest.age);
return exceptionTest;
}
}
运行结果是
try age= 1
finally age= 3
3
接下来去掉return
public static ExceptionTest test2(){
ExceptionTest exceptionTest = new ExceptionTest();
try{
exceptionTest.age = 1;
System.out.println("try age= "+exceptionTest.age);
return exceptionTest;
}catch (Exception e){
exceptionTest.age = 2;
return exceptionTest;
}finally {
// exceptionTest = new ExceptionTest();
exceptionTest.age = 3;
System.out.println("finally age= "+exceptionTest.age);
}
}
运行结果是
try age= 1
finally age= 3
3
以上这两个例子都可以看到finally有没有return都会对返回值产生影响
总结:
在finally和try中对数据进行操作时, 要把数据分为基本数据类型和引用数据类型. 他们存在的地方不一样, 一个是栈区, 另一个是堆区
对于基本数据类型
-
在异常体系中, 若finally中存在return, 则try, catch中的语句失效
-
若finally中无return, try和catch中有, 则try, catch代码块先暂存代码块中的值, 然后执行finally代码块, 最后返回暂存值
对于引用数据类型
-
堆中存放了内存地址, 所以改变的不是地址, 而是地址的内容
-
所以无论finally中有无return, 都会对当前方法的返回值产生影响.