下面这段代码中,为什么
//对引用的对象也进行复制
o.p=(Professor)p.clone();
就能够实现深拷贝呢?
class Professor implements Cloneable
{
String name;
int age;
Professor(String name,int age)
{
this.name=name;
this.age=age;
}
public Object clone()
{
Object o=null;
try
{
o=super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
return o;
}
}
public class Student implements Cloneable
{
String name;
int age;
Professor p;
Student(String name,int age,Professor p)
{
this.name=name;
this.age=age;
this.p=p;
}
public Object clone()
{
Student o=null;
try
{
o=(Student)super.clone();
}
catch(CloneNotSupportedException e)
{
System.out.println(e.toString());
}
//对引用的对象也进行复制
o.p=(Professor)p.clone();
return o;
}
public static void main(String[] args)
{
Professor p=new Professor("wangwu",50);
Student s1=new Student("zhangsan",18,p);
Student s2=(Student)s1.clone();
s2.p.name="lisi";
s2.p.age=30;
//学生1的教授不 改变。
System.out.println("name="+s1.p.name+","+"age="+s1.p.age);
System.out.println("name="+s2.p.name+","+"age="+s2.p.age);
}
}
巴扎黑2017-05-17 10:09:33
这只是表面上看起来是“深拷贝”, 实际上Student、Professor都没有实现深拷贝。
你在main方法增加几个输出:
Professor p=new Professor("wangwu",50);
Student s1=new Student("zhangsan",18,p);
Student s2=(Student)s1.clone();
System.out.println(s1.p == s2.p); //false
System.out.println(s1.name == s2.name); // true
System.out.println(s1.p.name == s2.p.name); //true
s2.p.name="lisi";
s2.p.age=30;
//学生1的教授不 改变。
System.out.println("name="+s1.p.name+","+"age="+s1.p.age);
System.out.println("name="+s2.p.name+","+"age="+s2.p.age);
System.out.println(s1.name == s2.name); //true
System.out.println(s1.p.name == s2.p.name); //false
即可看到,s1,s2的name仍然是"==", 在未set p.name时其name也为"==", 所以说都没有实现深拷贝。
当你set s2.p.name时,s2.p.name指向了另一个字符串常量的地址,所以(s1.p.name == s2.p.name); //false
天蓬老师2017-05-17 10:09:33
并不是深拷贝, 你可以试一下clone得到的professor.name
与原来的professor.name
是==
的, 说明String还是引用的原来的
淡淡烟草味2017-05-17 10:09:33
jdk clone方法的默认实现都是value copy,对于基本类型,就是把copy值。对于引用,就是copy引用所指向的地址。
所以如果没有o.p=(Professor)p.clone();
这段代码,那么原对象和clone对象的p,引用的都是同一个Professor对象,也就是浅copy。