Ausführliche Erklärung zum Klonen von Java-Objekten

Überblick: Wenn wir ein Objekt erstellen, werden die darin enthaltenen Eigenschaften initialisiert, und die Klonmethode wird verwendet, um den initialisierten Wert zu speichern.Normalerweise sehen wir am häufigsten, dass eine Referenz auf ein Objekt auf ein anderes Objekt verweist, nicht auf Two Objekte entstehen.

 Person p1 = new Person(100,"jim");
        Person p2 = p1;

        System.out.println(p1==p2);//true

Beim Klonen werden definitiv zwei Objekte erstellt

 Person p1 = new Person(100,"jim");
        Person p2 =p1.clone();//克隆的新对象

        System.out.println(p1==p2);//false

Das Klonen wird in flaches Klonen (ShallowClone) und tiefes Klonen (DeepClone) unterteilt.

In der Java-Sprache werden Datentypen in Werttypen (Basisdatentypen) und Referenztypen unterteilt. Werttypen umfassen einfache Datentypen wie int, double, byte, boolean und char, und Referenztypen umfassen komplexe Typen wie Klassen, Schnittstellen und Arrays. Der Wert des Basistyps kann direkt kopiert werden, der Referenztyp kann nur die Referenzadresse kopieren. Der Hauptunterschied zwischen flachem Klonen und tiefem Klonen besteht also darin, ob es die Duplizierung von Elementvariablen von Referenztypen unterstützt.

System.

flacher Klon

Wenn beim flachen Klonen die Mitgliedsvariable des Prototypobjekts ein Werttyp ist, wird eine Kopie in das Klonobjekt erstellt; wenn die Mitgliedsvariable des Prototypobjekts ein Referenztyp ist, wird die Adresse des Referenzobjekts kopiert das Klonobjekt, also der Prototyp. Die Mitgliedsvariablen des Objekts und des geklonten Objekts zeigen auf dieselbe Speicheradresse. Einfach ausgedrückt werden beim flachen Klonen beim Kopieren des Objekts nur es selbst und die darin enthaltenen Elementvariablen des Werttyps kopiert, während die Elementobjekte des Referenztyps nicht kopiert werden.

Methode zur Realisierung:

1. In der Sprache Java kann flaches Klonen erreicht werden, indem die Methode clone() der Klasse Object überschrieben wird.

2. Stellen Sie BeanUtils.copyProperties(source,target) im Spring-Framework bereit;

Hier demonstrieren wir hauptsächlich die Implementierung, indem wir die Klonmethode im Objekt umschreiben

1. Definieren Sie zuerst eine Klasse (die Klasse, die geklont werden muss)

public class Person implements  Cloneable{

     int num;
     String name;
     Address address;

    public Person() {
    }

    public Person(int num, String name) {
        this.num = num;
        this.name = name;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    protected Person clone() throws CloneNotSupportedException {
        Person person = (Person)super.clone();
        return person;
    }

    @Override
    public String toString() {
        return "Person{" +
                "num=" + num +
                ", name='" + name + '\'' +
                ", address=" + address +
                '}';
    }
}

2. Sie können sehen, dass die Klasse „Person“ mit der Klasse „Adresse“ verknüpft ist, und sie ausschreiben

public class Address  {

     String  address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }
}

3. Schreiben Sie eine Testklasse zum Testen

public class Test {

    public static void main(String[] args) throws CloneNotSupportedException {

        Address address = new Address();
                address.setAddress("汉中");

        Person p1 = new  Person(100,"jim");
               p1.setAddress(address);

        Person p2 =p1.clone();
               p2.setName("tom");
               address.setAddress("西安");

        System.out.println(p1); // jim   西安
        System.out.println(p2);// tom    西安
    }
}

Sehen Sie sich zuerst das Namensattribut an, der Name von p1 ist jim, ein anderes Objekt p2 wird geklont und der Name wird in tom geändert, da es zwei Objekte gibt, sodass die Ausgabeergebnisse unterschiedlich sind.

Betrachtet man die zugehörigen Objekte erneut, wird die Adresse mit Hanzhong-Informationen zuerst zu p1 hinzugefügt, sodass die aktuelle Adresse in p1 Hanzhong ist.Nach dem Klonen von p2 wird tatsächlich nur die Adresse für Adresse geklont, sodass p1 und p2 auf beide It verweisen ist die gleiche Adresse, also sind sie alle Hanzhong, und nach einer weiteren Überarbeitung sind sie alle Xi'an.

Beim flachen Klonen wird also nur die Adresse der Referenztypvariablen geklont.

tiefer Klon

Beim Deep Cloning wird unabhängig davon, ob die Mitgliedsvariable des Prototypobjekts ein Werttyp oder ein Referenztyp ist, eine Kopie auf das geklonte Objekt erstellt, und beim Deep Cloning wird auch eine Kopie aller Referenzobjekte des Prototypobjekts kopiert das geklonte Objekt. Einfach ausgedrückt werden beim Deep Cloning zusätzlich zum Kopieren des Objekts selbst alle im Objekt enthaltenen Mitgliedsvariablen ebenfalls kopiert

Wenn Sie tiefes Klonen in der Sprache Java implementieren müssen, können Sie es implementieren, indem Sie die Methode clone() der Klasse Object überschreiben , oder Sie können es durch Serialisierung (Serialization) und andere Methoden implementieren . Serialisierung ist der Vorgang des Schreibens eines Objekts in einen Stream.Das in den Stream geschriebene Objekt ist eine Kopie des ursprünglichen Objekts,und das ursprüngliche Objekt existiert noch im Arbeitsspeicher. Die durch Serialisierung erzielte Kopie kann nicht nur das Objekt selbst kopieren, sondern auch die Member-Objekte, auf die es sich bezieht, kopieren.Deshalb kann durch das Schreiben des Objekts in einen Stream durch Serialisierung und das Auslesen aus dem Stream Deep Cloning realisiert werden. Es sollte beachtet werden, dass die Klasse des Objekts, das die Serialisierung realisieren kann, die Serializable-Schnittstelle implementieren muss, andernfalls kann die Serialisierungsoperation nicht realisiert werden

1. Überschreiben Sie die Klonmethode in der Objektklasse

1. Definieren Sie zuerst eine Klasse (die Klasse, die geklont werden muss) und fügen Sie eine Codezeile zum Klonen des Adressobjekts im Vergleich zum obigen flachen Klon hinzu

public class Person implements  Cloneable{

     int num;
     String name;
     Address address;

    public Person() {
    }

    public Person(int num, String name) {
        this.num = num;
        this.name = name;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    protected Person clone() throws CloneNotSupportedException {
        Person person = (Person)super.clone();
        person.address = (Address)address.clone();   //深度复制  联同person中关联的对象也一同克隆.
        return person;
    }

    @Override
    public String toString() {
        return "Person{" +
                "num=" + num +
                ", name='" + name + '\'' +
                ", address=" + address +
                '}';
    }
}

2. Adresse wird ausgeschrieben, im Vergleich zum flachen Klon oben gibt es eine weitere Klonmethode, die die Objektklasse neu schreibt

public class Address  {

     String  address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }

   @Override
    protected Address clone() throws CloneNotSupportedException {
        return (Address)super.clone();
    }
}

3. Still Test Testklasse

public class Test {

    public static void main(String[] args) throws CloneNotSupportedException {

        Address address = new Address();
                address.setAddress("汉中");

        Person p1 = new  Person(100,"jim");
               p1.setAddress(address);

        Person p2 =p1.clone();
               p2.setName("tom");
               address.setAddress("西安");

        System.out.println(p1); // jim   西安
        System.out.println(p2);// tom    汉中
    }
}

Das Ergebnis wird diesmal anders sein, da der tiefe Klon nicht nur sich selbst klont, sondern auch die Objekte der zugehörigen Klassen klont, sodass der ursprüngliche Hanzhong, der in p1 gespeichert ist, in p2 geklont wird und die letzte Zeile, die in Xi'an geändert wurde, The ist ursprüngliches Adressobjekt, die ursprüngliche Adresse wurde geklont und in p2 gespeichert

2. Serialisierung (Serialisierung) Weg

Wenn der Klasse, die geklont werden muss, zu viele Objekte anderer Klassen zugeordnet sind, wird es viel Zeit in Anspruch nehmen, die zugeordneten Objekte einzeln zu klonen, wenn Sie weiterhin Deep Cloning verwenden, und die Serialisierungsmethode kann alle zugeordnet machen Objekte in der Klasse Verwandeln Sie es in einen Flow und klonen Sie es in Colleges und Universitäten.

1. Oder erstellen Sie ein Objekt, das der geklonten Klasse zugeordnet ist

public class Address  implements Serializable {

     String  address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }

}

2. Person-Klasse, die eine Klonmethode ihrer eigenen Serialisierungsmethode schreibt

public class Person implements Serializable {

     int num;
     String name;
     Address address;

    public Person() {
    }

    public Person(int num, String name) {
        this.num = num;
        this.name = name;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    /**
     * 自定义克隆方法
     * @return
     */
    public Person myclone() {
            Person person = null;
              try { // 将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝
                     ByteArrayOutputStream baos = new ByteArrayOutputStream();
                      ObjectOutputStream oos = new ObjectOutputStream(baos);
                      oos.writeObject(this);
            // 将流序列化成对象
                    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
                     ObjectInputStream ois = new ObjectInputStream(bais);
                     person = (Person) ois.readObject();
                  } catch (IOException e) {
                     e.printStackTrace();
                  } catch (ClassNotFoundException e) {
                     e.printStackTrace();
                 }
             return person;
          }


    @Override
    public String toString() {
        return "Person{" +
                "num=" + num +
                ", name='" + name + '\'' +
                ", address=" + address +
                '}';
    }
}

3. Testklassentest

public class Test {

    public static void main(String[] args) throws CloneNotSupportedException {

        Address address = new Address();
                address.setAddress("汉中");

        Person p1 = new  Person(100,"jim");
        p1.setAddress(address);

        Person p2 =p1.myclone();
               p2.setName("tom");
               address.setAddress("西安");

        System.out.println(p1);jim   西安
        System.out.println(p2);tom   汉中
    }
}

Daher hängt die Auswahl von der jeweiligen Situation ab

Ich denke du magst

Origin blog.csdn.net/weixin_71243923/article/details/128959956
Empfohlen
Rangfolge