Java Language
Object klonen
Zoeken…
Opmerkingen
Klonen kan lastig zijn, vooral als de velden van het object andere objecten bevatten. Er zijn situaties waarin u een diepe kopie wilt uitvoeren in plaats van alleen de veldwaarden te kopiëren (dwz verwijzingen naar de andere objecten).
De bottom line is kloon is gebroken , en je moet twee keer nadenken voordat zij wordt Cloneable
interface en overschrijven van de clone
-methode. De clone
wordt gedeclareerd in de klasse Object
en niet in de Cloneable
interface, dus Cloneable
functioneert niet als een interface omdat er geen openbare clone
is. Het resultaat is dat het contract voor het gebruik van clone
dun is gedocumenteerd en zwak wordt afgedwongen. Een klasse die clone
overschrijft, vertrouwt bijvoorbeeld soms op alle bovenliggende klassen die ook clone
overschrijven. Ze worden hiertoe niet gedwongen en als ze dat niet doen, kan uw code uitzonderingen veroorzaken.
Een veel betere oplossing voor het bieden van kloonfunctionaliteit is het bieden van een kopieerconstructeur of kopieerfabriek . Raadpleeg Effectief Java- item 11 van Joshua Bloch : oordeelkundig kloon overschrijven.
Klonen met behulp van een copy constructor
Een eenvoudige manier om een object te klonen is door een kopieerconstructor te implementeren.
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 door Clonable-interface te implementeren
Een object klonen door de Cloneable- interface te implementeren.
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 met een ondiep exemplaar
Standaardgedrag bij het klonen van een object is het uitvoeren van een ondiepe kopie van de velden van het object. In dat geval bevatten zowel het oorspronkelijke object als het gekloonde object verwijzingen naar dezelfde objecten.
Dit voorbeeld laat dat gedrag zien.
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 met een diepe kopie
Om geneste objecten te kopiëren, moet een diepe kopie worden uitgevoerd, zoals getoond in dit voorbeeld.
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 met behulp van een kopieerfabriek
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)
}
}