```java
//编写一个方法copyPerson,可以复制一个Person对象,返回复制的对象。克隆对象,
//注意要求得到新对象和原来的对象是两个独立的对象,只是他们的属性相同
public class test {
//编写一个main方法
public static void main(String[] args) {
Person p = new Person();
p.name = "milan";
p.age = 100;
//创建tools
MyTools tools = new MyTools();
Person p2 = tools.copyPerson(p);
//到此 p 和 p2是Person对象,但是是两个独立的对象,属性相同
System.out.println("p的属性 age=" + p.age + " 名字=" + p.name);
System.out.println("p2的属性 age=" + p2.age + " 名字=" + p2.name);
//这里老师提示: 可以同 对象比较看看是否为同一个对象
System.out.println(p == p2);//false
p.name ="xyz";
System.out.println("======================");//用来区分上面的输出
System.out.println("p的属性 age=" + p.age + " 名字=" + p.name);
System.out.println("p2的属性 age=" + p2.age + " 名字=" + p2.name);
}
}
class Person {
String name;
int age;
}
class MyTools {
public Person copyPerson(Person p) {
//创建一个新的对象
Person p2 = new Person();
p2.name = p.name; //把原来对象的名字赋给p2.name
p2.age = p.age; //把原来对象的年龄赋给p2.age
return p2;
}
}
在学习方法的内存机制的时候,教程说对象中的属性如果是字符串,那么这个字符串会存放在方法区,在对象中存的是存字符串的地址,那么如果是这样的话,p对象改name属性的时候,方法区中的字符串会变成xyz,那么访问p2对象的name应该也会变成xyz才对呀,因为访问name的时候是一个地址,到地址中去找位于方法区的字符串变成了xyz,但是通过运行代码发现,p2的name依然是milan,并没有变成xyz,麻烦解答一下,谢谢
当然,你能理解内存模型亦或是理解堆栈相关知识,其实就蛮好理解的。
p2.name = p.name; 这里赋值,对于引用类型,只是将p2.name的引用 指向了p.name引用的那块内存地址中的值。此时他们指向的是内存中的同一个地址。
p.name ="xyz"; 当你把p.name重新赋值,并不是将原来的地址的值改变了,而是将p.name指向了内存中所谓的"xyz"的这个地址。此时p.name和p2.name的指向是不同的地址,当然就不一样了。
在内存模型中,堆是线程共享的(引用类型,如对象,类中的全局变量),而栈是线程私有的(常见的有局部变量)。你所说的是改变栈中的值,那就会一起变。引用类型赋值改变的是内存地址,也就是一个引用指向。要真正改变内存堆中或常量池中的值才会真的改变。