本文主要举例说明为什么java是值传递、普通类对象的传递和String类型的传递过程。
先看下代码,很简单
Person类
public class Person {
public String name;
public Person(String name) {
this.name = name;
}
}
测试方法:
public static void test() {
Person p = new Person("Lilei");
System.out.println("PersonLilei : " + p.hashCode());
p = new Person("Haimeimei");
System.out.println("PersonHaimeimei : " + p.hashCode());
change(p);
System.out.println("PersonAfterChange : " + p.hashCode());
}
public static void change(Person pNew) {
System.out.println("PersonBeforeChange : " + pNew.hashCode());
pNew = new Person("Lucy");
System.out.println("PersonLucy : " + pNew.hashCode());
}
注:hashcode这里就用于表示物理地址。
运行结果
注:云状图表示堆存储空间,方块表示物理地址存放空间,菱形表示指针。
分析
创建了一个Lilei的Person对象,物理地址为1793467229,认为指针(变量)p,指向该物理地址(也就是p指针的值就是1793467229)。
创建了一个Haimeimei的对象,物理地址为723248511,然后p指针指向了723248511(也就是说,第一步创建的对象没有指针指向它了,理论上说,它可以被垃圾回收机制回收,当然,没有回收之前的Haimeimei对象还是存在在堆存储中的)。
这时候执行了一个change方法,把p指针的值作为参数传递进去,这时候我们打印结果是723248511,也就是和p的指向的物理地址相同,注意!虽然物理地址相同,可这两个指针其实是不一样的,我们可以认为这个新的指针叫pNew。
然后和前面一样,创建Lucy对象,物理地址:880282357,这时候pNew的值就是880282357
到这里其实就分析完毕了,当然上面讲的是普通的一个类对象(Person),下面按这个思路来看看String类对象的传递。
String类型传递
代码
public static void test() {
String p = "Lilei";
change(p);
System.out.println("p : " + p.name);
}
public static void change(String p2) {
p2 = "Haimeimei";
}
分析
在堆中创建一个String对象“Lilei”,物理地址假设为123,p变量的值就是123。
然后执行change方法,新建一个Haimeimei对象,物理地址为456,让p变量的值副本(当作一个新的指针p2)指向456。
执行完change后打印p的name字段,应该是多少?答案是:Lilei。因为p的值,也就是物理地址没变过,是123,而123的物理地址在堆中的对象就是“Lilei”。