Java 深淺拷貝

Java 深拷貝和淺拷貝java

  在淺拷貝中,若是原型對象的成員變量是基本類型時,將複製一份給克隆對象;若是原型對象的成員變量是引用類型,則將引用對象的地址複製一份給克隆對象,也就是說原型對象和克隆對象的成員變量指向相同的內存地址。ide

  對應的深拷貝,若是時成員變量爲引用對象也複製一份給複製對象。測試

  

實現this

  一、新建一個 Person 和 PersonId 類spa

public class Person implements Cloneable { private String name; private int age; private PersonId personId; public Person(String name, int age, int id) { this.name = name; this.age = age; this.personId = new PersonId(id); } public void setId(int id) { personId.setId(id); } public void setAge(int age) { this.age = age; } public Person clone() throws CloneNotSupportedException { Person cloned = (Person)super.clone(); return cloned; }  @Override public String toString() { return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", personId=" + personId +
                '}'; } }
class PersonId{ private int id; public PersonId(int id) { this.id = id; } public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "PersonId{" +
                "id=" + id +
                '}'; } }

  二、使用 CloneDemo 類來測試淺拷貝code

public class CloneDemo { public static void main(String[] args) throws CloneNotSupportedException { Person person = new Person("zhangsan",20,123); Person cloned = person.clone(); System.out.println("original: "+person); System.out.println("cloned: "+cloned); System.out.println("Modify Age and Id: "); cloned.setAge(55); cloned.setId(234); System.out.println("original: "+person); System.out.println("cloned: "+cloned); } }

  三、輸出對象

 

   能夠看到咱們修改了拷貝對象的年齡和ID,原始對象的年齡仍是20,原始對象的ID卻變成了咱們修改後的值,咱們並無對原始對象的ID進行修改,這裏說明淺拷貝對於對象僅僅是拷貝了一個對象的引用而已。blog

  四、接下來咱們修改 Person 類的 clone() 方法,實現深拷貝。接口

public Person clone() throws CloneNotSupportedException { Person cloned = (Person)super.clone(); cloned.personId = personId.clone(); return cloned; }

  五、爲了拷貝PersonId 的對象咱們須要PersonId 類實現 Cloneable 接口內存

class PersonId implements Cloneable{ private int id; public PersonId(int id) { this.id = id; } public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "PersonId{" +
                "id=" + id +
                '}'; } public PersonId clone() throws CloneNotSupportedException { return (PersonId)super.clone(); } }

  六、再次運行 CloneDemo 輸出

 

   能夠看到 原始對象的ID 值沒有被修改。

  七、使用序列化實現深拷貝

import java.io.*; public class Person implements Cloneable, Serializable { private String name; private int age; private PersonId personId; public Person(String name, int age, int id) { this.name = name; this.age = age; this.personId = new PersonId(id); } public void setId(int id) { personId.setId(id); } public void setAge(int age) { this.age = age; } public Person clone() throws CloneNotSupportedException { try { ByteArrayOutputStream bout = new ByteArrayOutputStream(); try(ObjectOutputStream out = new ObjectOutputStream(bout)) { out.writeObject(this); } try(InputStream bin = new ByteArrayInputStream(bout.toByteArray())){ ObjectInputStream in = new ObjectInputStream(bin); return (Person)in.readObject(); } } catch (IOException | ClassNotFoundException e) { CloneNotSupportedException e2 = new CloneNotSupportedException(); e2.initCause(e); throw e2; } } @Override public String toString() { return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", personId=" + personId +
                '}'; } } class PersonId implements Cloneable,Serializable{ private int id; public PersonId(int id) { this.id = id; } public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "PersonId{" +
                "id=" + id +
                '}'; } public PersonId clone() throws CloneNotSupportedException { return (PersonId)super.clone(); } }

  全部寫入流的對象都要實現 Serializable 接口。將 Person 對象寫入流中而後再從流中讀取出來實現深拷貝。

   輸出:

總結

  若要實現深拷貝,若是對象中引用了其餘對象,必須將引用的對象也克隆。

相關文章
相關標籤/搜索