搜索

首页  >  问答  >  正文

关于java深拷贝的疑问

下面这段代码中,为什么

//对引用的对象也进行复制
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); 
 } 
} 
ringa_leeringa_lee2775 天前504

全部回复(4)我来回复

  • 巴扎黑

    巴扎黑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

    回复
    0
  • 淡淡烟草味

    淡淡烟草味2017-05-17 10:09:33

    你这个是浅复制,只能复制基本的数据类型,要复制对象成员变量,还需要调用该成员变量的clone方法,我是这么理解的,多次浅复制实现深复制

    回复
    0
  • 天蓬老师

    天蓬老师2017-05-17 10:09:33

    并不是深拷贝, 你可以试一下clone得到的professor.name与原来的professor.name==的, 说明String还是引用的原来的

    回复
    0
  • 淡淡烟草味

    淡淡烟草味2017-05-17 10:09:33

    jdk clone方法的默认实现都是value copy,对于基本类型,就是把copy值。对于引用,就是copy引用所指向的地址。

    所以如果没有o.p=(Professor)p.clone();这段代码,那么原对象和clone对象的p,引用的都是同一个Professor对象,也就是浅copy。

    回复
    0
  • 取消回复