java中深拷贝和浅拷贝

时间:2022-06-07 22:33:44

 

先看代码,从结果中分析和总结深拷贝和浅拷贝的区别和实质。

 

publicclass Father {

   public String name;

   public int age;

   public Father(String name,int age){

      this.name=name;

      this.age=age;

   }

}

public class Person implements Cloneable{

   public String name;

   private int age;

   public Father father;

   public Person(String name,int age,Father father){

      this.name=name;

      this.age=age;

      this.father=father;

   }

   @Override

   protected Object clone(){

      Person p=null;

      try {

         p=(Person)super.clone();

      } catch (CloneNotSupportedException e) {

         e.printStackTrace();

      }

      return p;

   }

   @Override

   public String toString() {

      return"Person [name=" +name + ", age=" +age + ", fatherName=" +father.name+",fatherAge="+father.age

            + "]";

   }

}

客户端程序如下:

   publicstaticvoid main(String[] args) {

      Person person1 = new Person("son",14,new Father("father", 52));

      Person person2=person1;

      System.out.println(person1==person2);//指向同一个对象

      Person person3=(Person) person1.clone();

      System.out.println(person1==person3);

      person3.father.name="wangwu";

      System.out.println(person1.father.name);

   }

打印结果是:

true

false

Wangwu

我们可以看出person1person2是指向同一个对象而person1person3指向不同的对象,通过修改person3futhernameperson1的也改变了,也就是说person1person3futher成员变量指向同一个地址,这时候我们就说这种拷贝是浅拷贝。

 修改一下程序将Futher类也实现Cloneable接口

publicclass Father implements Cloneable{

   public String name;

   public int age;

   public Father(String name,int age){

      this.name=name;

      this.age=age;

   }

   @Override

public Object clone()throws CloneNotSupportedException   {

      return super.clone();

   }

}

Person类的代码也作稍微的修改

public class Person implements Cloneable{

   public String name;

   private int age;

   public Father father;

   public Person(String name,int age,Father futher){

      this.name=name;

      this.age=age;

      this.father=father;

   }

   @Override

   protected Object clone(){

      Person p=null;

      try {

         p=(Person)super.clone();

         p.futher=(Father)father.clone();

      } catch (CloneNotSupportedException e) {

         e.printStackTrace();

      }

      return p;

   }

   @Override

   public String toString() {

      return"Person [name=" +name + ", age=" +age + ", fatherName=" +father.name+",fatherAge="+father.age

            + "]";

   }

}

这样打印的结果是:

true

false

Father

这种拷贝是深拷贝。

浅拷贝是指拷贝对象时仅仅拷贝对象本身(对象中的基本数据类型),而不拷贝对象中包含的引用数据类型,拷贝过后引用数据类型指向被拷贝对象中引用数据类型变量的地址。深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。

深拷贝代码可以这样写:

public Object clone()throws CloneNotSupportedException {

      Person p=new Person();

      p.age=this.age;

      p.name=this.name;

      p.father=new Futher(father.name,father.age);

      returnp;

   }

对于拷贝可能我们比较常用的方式是将对象序列化,序列化拷贝对象的缺点是效率比较低。

修改代码如下:

public class Father implements Serializable{

   private static final longserialVersionUID = 1L;

   public String name;

   public int age;

   public Father(String name,int age){

      this.name=name;

      this.age=age;

   }

}

public class Person implements Serializable{

   private static final long serialVersionUID = 1L;

   public String name;

   private int age;

   public Father father;

   public Person(String name,int age,Father father){

      this.name=name;

      this.age=age;

      this.father=father;

   }

 

   public Object deepCopy() throws IOException,ClassNotFoundException{

      //写对象到流中

  ByteArrayOutputStream os = new ByteArrayOutputStream();

   ObjectOutputStream oos=new ObjectOutputStream(os);

      oos.writeObject(this);

      //流中读取对象

      ObjectInputStream ois=new ObjectInputStream(newByteArrayInputStream(os.toByteArray()));

      Object readObject = ois.readObject();

      return readObject;

   }

   @Override

   public String toString() {

      return"Person [name=" +name + ", age=" +age + ", fatherName=" +father.name+",fatherAge="+father.age

            + "]";

   }

}

客户端调用deepCopy()方法也可以实现深拷贝。