Pourquoi la méthode clone() protégé en java.lang.L'objet?

Quelle est la raison précise pour laquelle clone() est défini comme protégé dans java.lang.Object ?

98
demandé sur Paul Bellora 2009-07-16 20:28:37

11 réponses

le fait que le clone soit protégé est extrêmement douteux - tout comme le fait que la méthode clone n'est pas déclarée dans l'interface Cloneable .

il rend la méthode assez inutile pour prendre des copies de données parce que vous ne pouvez pas dire :

if(a instanceof Cloneable) {
    copy = ((Cloneable) a).clone();
}

je pense que le dessin de Cloneable est maintenant largement considéré comme une erreur (citation ci-dessous). Je voudrais normalement être capable de faire des implémentations d'une interface Cloneable mais ne font pas nécessairement l'interface Cloneable (similaire à l'utilisation de Serializable ). Cela ne peut se faire sans réflexion:

ISomething i = ...
if (i instanceof Cloneable) {
   //DAMN! I Need to know about ISomethingImpl! Unless...
   copy = (ISomething) i.getClass().getMethod("clone").invoke(i);
}

Citation de Java efficace de Josh Bloch :

"l'interface Cloneable a été conçu comme une interface de mixin pour les objets de publicité qu'ils permettent clonage. Malheureusement, il ne parvient pas à servir à cette fin ... C'est un très atypique l'utilisation d'interfaces et de ne pas être imité ... Pour que la mise en œuvre de l'interface ait un effet quelconque sur une classe, elle et toutes ses superclasses doivent obéir à un protocole assez complexe, inexécutable et largement non documenté

97
répondu oxbow_lakes 2009-07-16 23:24:14

l'interface Clonable est juste un marqueur disant que la classe peut supporter le clone. La méthode est protégée parce que vous ne devriez pas l'appeler sur object, vous pouvez (et devriez) l'annuler en tant que public.

De Sun:

dans l'objet de la classe, la méthode clone() est déclarée protégée. Si tout ce que vous faites est implémenter Cloneable, seuls les sous-classes et les membres du même paquet pourront invoquer clone() sur l'objet. Pour permettre à toute la classe dans un paquet de accédez à la méthode clone (), vous devrez l'annuler et la déclarer publique, comme c'est fait ci-dessous. (Lorsque vous outrepassez une méthode, vous pouvez la rendre moins privée, mais pas plus privée. Ici, la méthode protected clone() dans Object est supplantée en tant que méthode publique.)

24
répondu Bill K 2009-07-16 16:38:54

clone est protégé parce que c'est quelque chose qui doit être écarté afin qu'il soit spécifique à la classe actuelle. Bien qu'il soit possible de créer une méthode publique clone qui clonerait n'importe quel objet, cela ne serait pas aussi bon qu'une méthode écrite spécifiquement pour la classe qui en a besoin.

7
répondu Andrew Hare 2009-07-16 16:30:29

la méthode du Clone ne peut être utilisée directement sur aucun objet, c'est pourquoi elle est destinée à être supplantée par la sous-classe.

bien sûr, il pourrait être public et tout simplement jeter une exception appropriée lorsque le clonage n'est pas possible, mais je pense que ce serait trompeur.

la façon dont clone est implémenté en ce moment vous fait penser à pourquoi vous voulez utiliser clone, et comment vous voulez que votre objet soit cloné.

4
répondu Silfverstrom 2009-07-16 16:34:10

il est protégé parce que l'implémentation par défaut fait une copie peu profonde de tous les champs (y compris privé), circumventing constructor . Ce n'est pas quelque chose qu'un objet peut être conçu pour traiter en premier lieu (par exemple, il peut garder une trace des instances d'objet créées dans une liste partagée, ou quelque chose de similaire).

pour la même raison, l'implémentation par défaut de clone() lancera si l'objet sur lequel elle est appelée n'implémente pas Cloneable . Il s'agit d'une opération potentiellement dangereuse avec des conséquences de grande envergure, et donc l'auteur de la classe doit explicitement opt-in.

2
répondu Pavel Minaev 2009-07-16 16:50:35

du javadoc de cloneable.

* By convention, classes that implement this interface (cloneable) should override 
* <tt>Object.clone</tt> (which is protected) with a public method.
* See {@link java.lang.Object#clone()} for details on overriding this
* method.

* Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
* Therefore, it is not possible to clone an object merely by virtue of the
* fact that it implements this interface.  Even if the clone method is invoked
* reflectively, there is no guarantee that it will succeed.

donc vous pouvez appeler clone sur chaque objet mais cela vous donnerait la plupart du temps pas les résultats que vous voulez ou une exception. Mais c'est seulement recommandé si vous implémentez clonable.

2
répondu Janusz 2009-07-16 17:02:49

IMHO c'est aussi simple que ça:

  • #clone ne doit pas être appelé sur des objets non clonables, donc il n'est pas rendu public
  • #clone doit être appelé par les sous-classes ob Object qui mettent en œuvre clonable pour obtenir la copie peu profonde de la classe de droite

Quelle est la bonne portée pour les méthodes qui doivent être appelables par des sous-classes, mais pas par d'autres classes?

C'est protected .

"151950920 des cours de" mise en œuvre Cloneable bien sûr, fera de cette méthode publique de sorte qu'il peut être appelé à d'autres classes.

2
répondu Michaela Elschner 2016-09-05 13:03:28

méthode Clone() a un contrôle interne "instance de Clonable ou pas".C'est ainsi que Java team pourrait penser restreindre l'utilisation inappropriée de la méthode clone ().méthode clone() est protégée, c'est à dire accessible par les sous-classes. Puisque object est la classe mère de toutes les sous-classes, la méthode Clone() peut donc être utilisée par toutes les classes infact si nous n'avons pas la vérification ci-dessus de 'instance of Cloneable'. C'est la raison pour laquelle Java team pourrait avoir pensé à restreindre l'utilisation inappropriée de clone() en ayant vérifiez dans la méthode clone () "est-ce qu'instance de Clonable'.

par conséquent, quelles que soient les classes implémenter cloneable peut utiliser la méthode clone() de classe objet.

aussi depuis qu'il a fait protégé, il est disponible pour seulement les sous-classes qui implémente l'interface clonable. Si nous voulons la rendre publique, cette méthode doit être remplacée par la sous-classe avec leur propre mise en œuvre.

0
répondu SARIKA 2018-08-17 21:07:23

oui, le même problème que j'ai rencontré. Mais je le résous en implémentant ce code

public class Side implements Cloneable {
    public Side clone() {

        Side side = null;
        try {
            side = (Side) super.clone();
        } catch (CloneNotSupportedException e) {
            System.err.println(e);
        }
        return side;
    }
}

comme l'a dit l'autre.

-2
répondu fyhao 2009-08-10 16:55:17

Eh bien, aussi les développeurs sun sont seulement humains, et ils ont en effet fait une énorme erreur pour mettre en œuvre la méthode clone comme protégé, la même erreur qu'ils ont mis en œuvre une méthode clone non-fonctionnement dans ArrayList! Donc, en général, il existe un malentendu beaucoup plus profond de programmeurs Java même expérimentés à propos de la méthode clone.

cependant, j'ai récemment trouvé une solution rapide et facile pour copier n'importe quel objet avec tout son contenu, peu importe comment il est construit et ce qu'il contient, voir ma réponse ici: Bug dans L'utilisation D'objet.clone ()

-2
répondu mark 2017-05-23 12:17:50

encore une fois, Java JDK framework montre une pensée brillante:

l'interface clonable ne contient pas de méthode "public T clone();" parce qu'elle agit plus comme un attribut (par ex. Serializable) qui permet à une instance d'être cloné.

il n'y a rien de mal à ce dessin parce que:

  1. " objet.clone () ne fera pas ce que vous voulez avec votre classe définie sur mesure.

  2. si vous avez des outils MyClass Cloneable => vous écrasez clone () avec "public Maclasse clone()"

  3. si vous avez MyInterface s'étend Cloneable et certains MyClasses mettre en œuvre MyInterface: définissez simplement " public MyInterface clone ();" dans l'interface et chaque méthode utilisant les objets MyInterface sera capable de les cloner, peu importe leur classe de MyClass.

-3
répondu Victor 2013-03-18 14:40:40