Suche…


Bemerkungen

Das Klonen kann schwierig sein, insbesondere wenn die Felder des Objekts andere Objekte enthalten. Es gibt Situationen, in denen Sie eine tiefe Kopie erstellen möchten, anstatt nur die Feldwerte zu kopieren (dh Verweise auf die anderen Objekte).

Unterm Strich ist Klon ist gebrochen , und Sie sollten sich zweimal überlegen , bevor Sie die Umsetzung Cloneable Schnittstelle und das Überschreiben der clone - Methode. Die clone Methode ist in der Object Klasse und nicht in der Cloneable Schnittstelle Cloneable funktioniert daher nicht als Schnittstelle, da es keine öffentliche clone Methode gibt. Das Ergebnis ist, dass der Vertrag für die Verwendung von clone dünn dokumentiert und schwach durchgesetzt wird. Eine Klasse, die den clone überschreibt, ist beispielsweise darauf angewiesen, dass alle übergeordneten Klassen den clone überschreiben. Sie werden dazu nicht erzwungen und wenn dies nicht der Fall ist, kann Ihr Code Ausnahmen auslösen.

Eine viel bessere Lösung für die Bereitstellung von Klonfunktionen ist das Bereitstellen eines Kopierkonstruktors oder einer Kopierfabrik . Siehe Joshua Blochs Effektives Java- Element 11: Überschreiben Sie den Klon mit Bedacht.

Klonen mit einem Kopierkonstruktor

Ein einfacher Weg, ein Objekt zu klonen, ist die Implementierung eines Kopierkonstruktors.

public class Sheep {

    private String name;

    private int weight;

    public Sheep(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }

    // copy constructor
    // copies the fields of other into the new object
    public Sheep(Sheep other) {
        this.name = other.name;
        this.weight = other.weight;
    }

}

// create a sheep
Sheep sheep = new Sheep("Dolly", 20);
// clone the sheep
Sheep dolly = new Sheep(sheep); // dolly.name is "Dolly" and dolly.weight is 20

Klonen durch Implementierung einer klonbaren Schnittstelle

Klonen eines Objekts durch Implementieren der Schnittstelle Cloneable .

public class Sheep implements Cloneable {

    private String name;

    private int weight;

    public Sheep(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

}

// create a sheep
Sheep sheep = new Sheep("Dolly", 20);
// clone the sheep
Sheep dolly =  (Sheep) sheep.clone(); // dolly.name is "Dolly" and dolly.weight is 20

Klonen beim Durchführen einer flachen Kopie

Das Standardverhalten beim Klonen eines Objekts besteht darin, eine flache Kopie der Felder des Objekts auszuführen. In diesem Fall enthalten sowohl das Originalobjekt als auch das geklonte Objekt Verweise auf dieselben Objekte.

Dieses Beispiel zeigt dieses Verhalten.

import java.util.List;

public class Sheep implements Cloneable {

    private String name;

    private int weight;

    private List<Sheep> children;

    public Sheep(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public List<Sheep> getChildren() {
        return children;
    }

    public void setChildren(List<Sheep> children) {
        this.children = children;
    }

}

import java.util.Arrays;
import java.util.List;

// create a sheep
Sheep sheep = new Sheep("Dolly", 20);

// create children
Sheep child1 = new Sheep("Child1", 4);
Sheep child2 = new Sheep("Child2", 5);

sheep.setChildren(Arrays.asList(child1, child2));

// clone the sheep
Sheep dolly =  (Sheep) sheep.clone();
List<Sheep> sheepChildren = sheep.getChildren();
List<Sheep> dollysChildren = dolly.getChildren();
for (int i = 0; i < sheepChildren.size(); i++) {
    // prints true, both arrays contain the same objects
    System.out.println(sheepChildren.get(i) == dollysChildren.get(i));
}

Klonen beim Durchführen einer tiefen Kopie

Um geschachtelte Objekte zu kopieren, muss eine tiefe Kopie ausgeführt werden, wie in diesem Beispiel gezeigt.

import java.util.ArrayList;
import java.util.List;

public class Sheep implements Cloneable {

    private String name;

    private int weight;

    private List<Sheep> children;

    public Sheep(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        Sheep clone = (Sheep) super.clone();
        if (children != null) {
            // make a deep copy of the children
            List<Sheep> cloneChildren = new ArrayList<>(children.size());
            for (Sheep child : children) {
                cloneChildren.add((Sheep) child.clone());
            }
            clone.setChildren(cloneChildren);
        }
        return clone;
    }

    public List<Sheep> getChildren() {
        return children;
    }

    public void setChildren(List<Sheep> children) {
        this.children = children;
    }

}

import java.util.Arrays;
import java.util.List;

// create a sheep
Sheep sheep = new Sheep("Dolly", 20);

// create children
Sheep child1 = new Sheep("Child1", 4);
Sheep child2 = new Sheep("Child2", 5);

sheep.setChildren(Arrays.asList(child1, child2));

// clone the sheep
Sheep dolly =  (Sheep) sheep.clone();
List<Sheep> sheepChildren = sheep.getChildren();
List<Sheep> dollysChildren = dolly.getChildren();
for (int i = 0; i < sheepChildren.size(); i++) {
    // prints false, both arrays contain copies of the objects inside
    System.out.println(sheepChildren.get(i) == dollysChildren.get(i));
}

Klonen mit einer Kopierfabrik

public class Sheep {

    private String name;
    
    private int weight;
    
    public Sheep(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }
    
    public static Sheep newInstance(Sheep other);
        return new Sheep(other.name, other.weight)
    }

}


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow