class Value{
public int i = 15;
}
public class Test{
public static void main(String argv[]){
Test t = new Test();
t.first();
}
public void first(){
int i = 5;
Value v = new Value(); /// 这里创建了第一个对象[1],由 v 引用
v.i = 25;
second(v, i); /// [1]的引用通过参数传进 second 方法,看 second
System.out.println(v.i); /// 这里的 v 仍然引用的 [1]
}
public void second(Value v, int i){ /// 这个 v 由外面传入,引用[1],是外面那个 v 的拷贝(仅是引用的拷贝,引用的都是[1])
i = 0;
v.i = 20;
Value val = new Value(); /// 创建 [2]
v = val; /// 内部的v引用[2],外部的v不变,仍引用[1]
System.out.println(v.i + " " + i);
}
}
public int i = 15;
}
public class Test{
public static void main(String argv[]){
Test t = new Test();
t.first();
}
public void first(){
int i = 5;
Value v = new Value(); /// 这里创建了第一个对象[1],由 v 引用
v.i = 25;
second(v, i); /// [1]的引用通过参数传进 second 方法,看 second
System.out.println(v.i); /// 这里的 v 仍然引用的 [1]
}
public void second(Value v, int i){ /// 这个 v 由外面传入,引用[1],是外面那个 v 的拷贝(仅是引用的拷贝,引用的都是[1])
i = 0;
v.i = 20;
Value val = new Value(); /// 创建 [2]
v = val; /// 内部的v引用[2],外部的v不变,仍引用[1]
System.out.println(v.i + " " + i);
}
}
第一个是在first方法里的,即Value v = new Value();
姑且叫做v1。
第二个是在second方法的参数里声明的v,即second(Value v
我们把它叫做v2。
现在来看,在first里先实例化了一个Value,我们把它叫做j1,并且用v1引用它。<<Value v = new Value();>>
接着给这个j1的属性i赋值为25。<<v.i = 25;>>
然后调用second,并且把上边的j1传入了这个second。<<second(v, i);>>
现在来看second的处理。
现在进入second,因为j1传入了这个second,所以v2引用了j1,也就是说现在v2和v1同时引用了j1。
接着给j1的i属性赋值为20。也就是说上边赋值好的25现在已经被替换为20了。<<v.i = 20;>>Now,我们又实例化一个Value,并且声明了一个val来引用这个实例。<<Value val = new Value();>>
我们把这个新的实例叫做j2,把这个val叫做v3。接着又把v2的引用指向v3,也就是说v2指向了j2这个实例。<<v = val;>>
现在打印v2引用的实例的i属性,即j2的i属性。<<System.out.println(v.i + " " + i); >>
因为j2实例化以后并没有对它进行赋值,所以它的i保留了初始的15。同时打印的那个i,你也可以看到它在second方法开始的地方被设为0了。你的第一行结果就出来了。现在second方法执行完毕,其中的v2和v3引用以及实例j2,它们的生命期到此结束。
现在看first的最后一行,它打印v1的i属性,由于v1一直指向j1,从未改变,j1的i属性前边已被改变为20。自然现在打出来也就是20了。