Java Language
Objektklonen
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)
}
}