今天对return和finally做一个彻底详细的总结吧!
1:无论程序从try或catch中返回,finally总会被执行。并且finally语句是在return语句执行之后、返回之前执行的。
try/finally:
public class tryDemo {
public static int show() {
try {
return 1;
}finally{
System.out.println("finally模块被执行");
}
}
public static void main(String args[]) {
System.out.println(show());
}
}
结果:
catch/finally:
public class tryDemo {
public static int show() {
try {
int a = 8/0;
return 1;
}catch (Exception e) {
return 2;
}finally{
System.out.println("finally模块被执行");
}
}
public static void main(String args[]) {
System.out.println(show());
}
}
结果:
2:finally中的语句对变量的修改是否生效要看变量的类型
1)如果return的数据是基本数据类型或文本字符串,则在finally中对该基本数据的改变不起作用,try中的return语句依然会返回进入finally块之前保留的值。
2)如果return的数据是引用数据类型,而在finally中对该引用数据类型的属性值的改变起作用,try中的return语句返回的就是在finally中改变后的该属性的值。
这里又顺便想到String这种情况,String字符串虽然为引用类型,但是在finally改变的时候,其实当于申请了一个新的字符串,所以原来地址的字符串并没有改变,所以finally中的改变不会生效。如把string由“123”改为“456”,效果如下图:
而若是用StringBuilder/StringBuffer的话,就是正经的引用类型变量了,比如给StringBuffer b 来append一个“456”,会是下图:
用代码验证一下:
public class TestTryCatch {
public static void main(String[] args)
{
TestTryCatch test = new TestTryCatch();
System.out.println(test.fun());
}
public StringBuilder fun()
{
StringBuilder s = new StringBuilder("Hello");
try
{
//doing something
s.append("Word");
return s;
}catch(Exception e){
return s;
}finally{
string.append("finally");
}
}
输出结果:HelloWordFinally
果然,finally里的修改生效,最终结果也就改变了。
3:若是finally中有return,则将会以finally中的return为准,try/catch中的return将会unreached。
public class TryTest{
public static void main(String[] args){
System.out.println(test());
}
private static int test(){
int num = 10;
try{
System.out.println("try");
return num += 80;
}catch(Exception e){
System.out.println("error");
}finally{
if (num > 20){
System.out.println("num>20 : " + num);
}
System.out.println("finally");
num = 100;
return num;
}
}
结果为:
try
num>20 : 90
finally
100
可见,如果try中没有异常,那么是会顺序执行return,将值保存到临时栈中,然后执行finally,如果finally中有return,此时会覆盖try中的返回值。