浏览论坛的时候看到这样一个问题:
package test;
public class Test {
public int inc() {
int x;
try {
x = 1;
return x;
} catch (Exception e) {
x = 2;
return x;
} finally {
x = 3;
}
}
public StringBuffer inc(StringBuffer x) {
try {
x.append("1");
x = new StringBuffer();
return x;
} catch (Exception e) {
x.append("2");
return x;
} finally {
x.append("3");
x = new StringBuffer("4");
}
}
public static void main(String[] args) {
int x = new Test().inc();
System.out.println(x);
StringBuffer x1 = new StringBuffer(), x2 = new Test().inc(x1);
System.out.println(x1);
System.out.println(x2);
}
}
问最终执行后台将会打印的结果,看了一下感觉很有意思,就看了一下,我们只要先了解try catch finally的执行顺序,再结合内存分配的只是很容易就搞定。
打印的结果为1,1,3,我们从内存的角度来了解一下,对于打印的第一个1,我们可以得出,finally总是会在try语句中return完成之前先执行,并且无论finally语句中对try语句中返回的变量做任何修改,它返回的依然是try中之前变量所指向的那块内存地址,对于finally总是会在try语句return之前执行,我们只要打印一下就可以知道。
那么我们来看一下打印的第一个1,在inc()方法中首先声明变量x并赋值1,:
然后在return之前执行finally中语句x=3;
虽然他改变了x的值,但是它返回的是他在try语句中返回变量所指向的那块内存,所以,我们得出:finally总是会在try语句中return完成之前先执行,并且无论finally语句中对try语句中返回的变量做任何修改,它返回的依然是try中之前变量所指向的那块内存地址。
接下来我们来用这个结论来打印x1,x2
我们先来看一下内存分配:
程序首先new了一个StringBuffer对象x1
接着通过调用Test类中的inc(StringBuffer x)来获取x2,对于
x2 = new Test().inc(x1);来说,它传进去的参数所指向的对内存也就是x指向的对内存,也就是说x=x1,
接下来执行try中语句:
x.append("1");
x = new StringBuffer();
x经过append之后内存中变为1,之后x又重新指向一块新的内存,而x1没变
所以打印的x1为1,接下来执行finally语句中:
x.append("3");
x = new StringBuffer("4");
x.append('3')之后又重新指向了一块新内存,但是根据之前的结论,他返回的是try语句中返回变量所指向的内存,所以打印x2为3。
这样我们就可以得出结论:
finally总是会在try语句中return完成之前先执行,并且无论finally语句中对try语句中返回的变量做任何修改,它返回的依然是try中之前变量所指向的那块内存地址。
下面是从网上搜的一些作为参考。
我们首先来了解一下try catch finally语句的执行顺序:
加入try语句中有return的话,finally语句总是会在try语句return之前执行。并且
1 、try、catch、finally语句中,在如果try语句有return语句,则返回的之后当前try中变量此时对应的值,此后对变量做任何的修改,都不影响try中return的返回值
2 、如果finally块中有return 语句,则返回try或catch中的返回语句忽略。
3 、如果finally块中抛出异常,则整个try、catch、finally块中抛出异常
如果有什么理解错误的希望给予指正。