Recherche…


Remarques

Le clonage peut être délicat, en particulier lorsque les champs de l'objet contiennent d'autres objets. Il existe des situations où vous souhaitez effectuer une copie complète , au lieu de copier uniquement les valeurs de champ (c.-à-d. Les références aux autres objets).

La ligne du bas est clone est cassé , et vous devriez réfléchir à deux fois avant d'implémenter l'interface Cloneable et de Cloneable la méthode de clone . Le clone méthode est déclarée dans l' Object classe et non dans la Cloneable interface, donc Cloneable ne fonctionne pas comme une interface , car il ne dispose pas d' un public clone méthode. Le résultat est que le contrat d'utilisation du clone est peu documenté et faiblement appliqué. Par exemple, une classe qui remplace le clone s'appuie parfois sur toutes ses classes parentes qui ont également la priorité sur le clone . Ils ne sont pas obligés de le faire, et s’ils ne le font pas, votre code peut générer des exceptions.

Une solution bien meilleure pour fournir une fonctionnalité de clonage consiste à fournir un constructeur de copie ou une fabrique de copies . Reportez-vous à l' article 11 de Java efficace de Joshua Bloch : remplacer judicieusement le clone.

Clonage à l'aide d'un constructeur de copie

Un moyen simple de cloner un objet consiste à implémenter un constructeur de 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

Clonage en implémentant l'interface Clonable

Clonage d'un objet en implémentant l'interface 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

Cloner en effectuant une copie superficielle

Le comportement par défaut lors du clonage d'un objet consiste à effectuer une copie superficielle des champs de l'objet. Dans ce cas, l'objet d'origine et l'objet cloné contiennent des références aux mêmes objets.

Cet exemple montre ce comportement.

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

Cloner en effectuant une copie en profondeur

Pour copier des objets imbriqués, une copie en profondeur doit être effectuée, comme illustré dans cet exemple.

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

Clonage à l'aide d'une fabrique de copies

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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow