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)
    }

}


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow