Java Language
Clonazione dell'oggetto
Ricerca…
Osservazioni
La clonazione può essere complicata, specialmente quando i campi dell'oggetto contengono altri oggetti. Vi sono situazioni in cui si desidera eseguire una copia profonda , invece di copiare solo i valori del campo (cioè i riferimenti agli altri oggetti).
La linea di fondo è clone è rotto , e si dovrebbe pensare due volte prima di implementare l'interfaccia Cloneable
e sovrascrivere il metodo clone
. Il metodo clone
è dichiarato nella classe Object
e non nell'interfaccia Cloneable
, quindi Cloneable
non funziona come interfaccia perché manca un metodo clone
pubblico. Il risultato è che il contratto per l'uso del clone
è sottilmente documentato e debolmente applicato. Ad esempio, una classe che sovrascrive il clone
volte si basa su tutte le sue classi genitore che sovrascrivono anche il clone
. Non sono forzati a farlo, e se non lo fanno, il tuo codice può generare eccezioni.
Una soluzione molto migliore per fornire funzionalità di clonazione è quella di fornire un costruttore di copia o una fabbrica di copie . Fai riferimento a Joshua Bloch's Effective Java Item 11: Override clone in modo giudizioso.
Clonazione usando un costruttore di copie
Un modo semplice per clonare un oggetto è implementare un costruttore di copie.
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
Clonazione implementando l'interfaccia Clonabile
Clonazione di un oggetto implementando l'interfaccia 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
Clonazione eseguendo una copia superficiale
Il comportamento predefinito durante la clonazione di un oggetto consiste nell'eseguire una copia superficiale dei campi dell'oggetto. In tal caso, sia l'oggetto originale che l'oggetto clonato, contengono riferimenti agli stessi oggetti.
Questo esempio mostra questo comportamento.
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));
}
Clonazione eseguendo una copia profonda
Per copiare oggetti nidificati, è necessario eseguire una copia profonda , come mostrato in questo esempio.
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));
}
Clonazione utilizzando una fotocopiatrice
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)
}
}