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();// 如果在里面加参数例如这样new StringBuffer("5")结果就变了
return x;
} catch (Exception e) {
x.append("2");
return x;
} finally {
x.append("3");
x = new StringBuffer("4");
//这后面加return x;也会变
}
}
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);
}
}问:new StringBuffer();是否是重新开辟了一块内存,在这单中x1,和x2的指向是否有变化?stringbuffer
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();// 如果在里面加参数例如这样new StringBuffer("5")结果就变了
return x;
} catch (Exception e) {
x.append("2");
return x;
} finally {
x.append("3");
x = new StringBuffer("4");
//这后面加return x;也会变
}
}
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);
}
}问:new StringBuffer();是否是重新开辟了一块内存,在这单中x1,和x2的指向是否有变化?stringbuffer
String 内存地址是不变的
System.out.println(x1);
System.out.println(x2);
这要是折后面三个语句的问题,x1传入后执行 x.append("1");
那x1就是1,之后执行这一句
x = new StringBuffer();
那么是说x1已经更改了引用了啊?指向了空,可为什么还是1.
// 如果在里面加参数例如这样new StringBuffer("5")结果就变了
输出的x2变为了53了。
2、finally 关键字是在运行try里面的return 语句后才会被执行的,其实x = new StringBuffer("4"); x的值已经被更改了,但是因为try里面的return已经把值返回给主调程序,所以就算更改了也无法返回数值。
第一处这里只是x更该了引用x1 并没;
第2处new StringBuffer("5")时x引用的对象是值是5,然后return x,返回的是这时候x引用的对象,在通过finally里的x.append("3")使其引用的对象值变为了"53",所以这样的结果
x = new StringBuffer();
return x;对于新对象,在finally里进行了 x.append("3");的操作,使inc(x1)返回的是3的对象,之后变量x又指向新地址,这个地址没什么用了这个东西一看还真比较晕乎,debug一下思路会清晰一些的。
所有new都重开内存
1、 call by reference
2、 finally执行的时机首先,在java中,call by reference只是传入reference 变量的值赋予子函数的局部变量,并不是真的把引用变量传进去。结合这次具体的例子,则为变量x1指向的地址,赋给子函数中的局部变量x。这样,x1与x指向同一个对象,当修改对象的内容时,如x.append("1"),会影响x1,因为x1指向的对象的内容发生了变化。但是,当局部变量x的值被修改,指向其他对象时,如x = new StringBuffer(),并不会影响x1。其次来看finally执行的时机。一般我们认为finally在renturn之前执行,但实际上在执行到return子句时,子函数会先将返回值放到主函数的“接收空间”中,再去执行finally中的内容。这样一来如果在finally中不重新return,是不会改变子函数的返回值的。在本例中,finally中有两次操作:一次修改了局部变量x指向的对象的内容x.append("3");一次修改了局部变量x的值,指向新的对象x = new StringBuffer("4")。因为函数返回值是x之前指向的对象,是在finally中的内容执行前就确定的,所以后一次操作(x = new StringBuffer("4"))对子函数的返回值是没有影响的。下面是执行过程的细节,如果上面的描述不够清晰,不好理解。可以先看一下下面的详细流程。StringBuffer x1 = new StringBuffer()
x2 = new Test().inc(x1)... StringBuffer inc(StringBuffer x) 子函数开始执行...
...x.append("1")
...x = new StringBuffer()
这里局部变量x指向的地址发生了变化,但x1并不会随之变化。
... return x
这时子函数会把返回值放入主函数用于接收的“空间中”,然后去执行finally中的内容,finally中的内容执行完成后才会结束子函数。
接着执行finally中的内容:
... x.append("3")
...x = new StringBuffer("4")
注意这里并没有改变子函数的返回值,仅仅是局部变量X指向的地址发生了变化。
理解这里后,可以明白这里对后来x2的赋值没有影响。
(如果你在finally中最后在return x一次,子函数的返回值会改变,后来x2赋值时,会指向和局部变量x相同的地址。)
...子函数执行结束,回到x2 = new Test().inc(x1)
接下来就会打印出结果。所以会出现“1”“3”。