Question

Dans Effective Java, l'auteur affirme que:

  

Si une classe implémente Cloneable,   La méthode clone de l'objet retourne une   champ par champ copie de l'objet;   sinon il jette   CloneNotSupportedException.

Ce que je voudrais savoir est ce qu'il entend avec copie champ par champ. Est-ce que cela signifie que si la classe a X octets dans la mémoire, il suffit de copier ce morceau de mémoire? Si oui, puis-je prendre tous les types de valeur de la classe d'origine seront copiés sur le nouvel objet?

class Point implements Cloneable{
    private int x;
    private int y;

    @Override
    public Point clone() {
        return (Point)super.clone();
    }
}

Si ce Object.clone() fait est un champ par copie sur le terrain de la classe Point, je dirais que je ne aurais pas besoin de copier explicitement les champs x et y, étant que le code ci-dessus sera plus que suffisant pour faire clone de la classe Point. C'est le bit de code suivant est redondant:

@Override
public Point clone() {
    Point newObj = (Point)super.clone();
    newObj.x = this.x; //redundant
    newObj.y = this.y; //redundant
}

Ai-je raison?

Je sais références de l'objet cloné pointeront automatiquement à l'endroit où les références de l'objet initial a, je ne suis pas sûr de ce qui se passe spécifiquement avec les types de valeur. Si quelqu'un pouvait indiquer clairement ce que la spécification de l'algorithme de Object.clone() est (dans un langage facile) qui serait super.

Était-ce utile?

La solution

Oui, un champ par copie sur le terrain signifie que lorsqu'il crée le nouvel objet (clone), la machine virtuelle Java copie la valeur de tous les champs de l'objet d'origine dans l'objet cloné. Malheureusement, cela ne signifie pas que vous avez une copie peu profonde. Si vous désirez une copie profonde, vous pouvez remplacer la méthode clone.

class Line implements Cloneable {

    private Point start;
    private Point end;

    public Line() {
        //Careful: This will not happen for the cloned object
        SomeGlobalRegistry.register(this);
    }

    @Override
    public Line clone() {
        //calling super.clone is going to create a shallow copy.
        //If we want a deep copy, we must clone or instantiate
        //the fields ourselves
        Line line = (Line)super.clone();
        //assuming Point is cloneable. Otherwise we will
        //have to instantiate and populate it's fields manually
        line.start = this.start.clone();
        line.end = this.end.clone;
        return line;
    }
}

Aussi une chose plus importante au sujet du clonage est, le constructeur de l'objet cloné est jamais appelé (seuls les champs sont copiés). Donc, si le constructeur initialise un objet externe, ou enregistre cet objet avec un certain registre, alors cela ne se produira pas pour l'objet cloné.

Personnellement, je préfère ne pas utiliser le clonage de Java. Au lieu de cela, je crée habituellement mes propres méthodes « duplication ».

Autres conseils

Cela signifie une copie peu profonde - les champs sont copiés, mais si vous avez des références, ce que ces points à n'est pas copié - vous aurez deux références au même objet, l'un dans l'ancien objet et un dans le nouveau, objet cloné. Cependant, pour les champs qui ont des types primitifs, le champ est les données elles-mêmes, de sorte qu'ils sont copiés indépendamment.

newObj.x = this.x; //redundant
newObj.y = this.y; //redundant

qui est juste -. Ceux-ci sont redondants, car ils ont déjà été copiés par le clone de l'objet () méthode

Pensée comme une copie de données est correcte. Les types primitifs sont copiés, et les références sont également copiés afin qu'ils pointent vers le même objet. Par exemple,

class A implements Cloneable {
  Object someObject;
}

A a = new A();
a.someObject = new Object();

A cloneA = (A)a.clone();
assert a.someObject==cloneA.someObject;

Le clone par défaut effectue peu profonde copie des valeurs. Pour les valeurs primitives, cela suffit et aucun travail supplémentaire est nécessaire.

Pour les objets, les eaux peu profondes copie des moyens de copie de la référence. Par conséquent, dans ces cas, une copie en profondeur est généralement nécessaire. L'exception à cela est lorsque la référence pointe vers un objet immuable. Les objets non modifiables ne peuvent pas avoir leur état apparent a changé, par conséquent, leurs références peuvent être copiés autour en toute sécurité. Par exemple, cela s'applique à la chaîne, Integer, Float, énumérations (sinon fait mutable par erreur).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top