Je pense que la conception de Cloneable est maintenant largement considérée comme une erreur (citation ci-dessous). Normalement j'veux être en mesure de faire des implémentations de l'interface Cloneable mais pas nécessairement l'interface Cloneable (similaire à l'utilisation de Serializable). Cela ne peut se faire sans réflexion:
ISomething i =...if(i instanceofCloneable){//DAMN! I Need to know about ISomethingImpl! Unless...
copy =(ISomething) i.getClass().getMethod("clone").invoke(i);}
Citation De Josh Bloch Effectif de Java:
"La Clonable interface a été conçue comme un mixin interface pour les objets pour faire de la publicité qu'ils permettent le clonage. Malheureusement, il ne parvient pas à servir à cette fin ... C'est un très atypique l'utilisation d'interfaces et de ne pas être émulé ... pour la mise en œuvre de l'interface pour avoir un effet sur une classe, elle et toutes ses super-classes doivent obéir à un assez complexe, inapplicable et en grande partie sans-papiers protocole"
Si l'objet n'est pas Clonable, puis Object clone() va jeter CloneNotSupportedException. Si vous avez besoin d'être Clonable si vous allez appeler super.clone() (résultant dans l'Objet.clone() appelée). Je ne vois pas comment un objet peut être sérialisé sans implémenter Serializable.
"Je pense que la conception de Clonable est maintenant largement considéré comme une erreur." [citation nécessaire]
Désolé, je n'était pas ce qui implique que. J'étais simplement ce qui implique que la "bonne" conception est de pas faire une interface étendre Serializable - c'est à implémentations de décider de mettre en œuvre Serializable. J'ai été l'extension à la Cloneable - il n'est pas quelque chose qui une interface doit s'étendre - mais une mise en œuvre d'une interface est libre d'être Cloneable. Le problème est que, si vous avez un paramètre du type d'interface, vous demandez, demandez-lui s'il est clonable; mais alors vous ne pouvez pas cloner!
Du Bloch efficace Java pp45. "La Clonable interface a été conçue comme un mixin interface pour les objets pour faire de la publicité qu'ils permettent le clonage. Malheureusement, il ne parvient pas à servir cette fin."
Également sur la même page: "C'est un très atypique l'utilisation d'interfaces et de ne pas être émulé" et "pour la mise en œuvre de l'interface pour avoir un effet sur une classe, elle et toutes ses super-classes doivent obéir à un assez complexe, inapplicable et en grande partie sans-papiers protocole"
Josh est guère effusive est-il?
Citation ajoutée à l'entrée principale
Le mot "erreur" n'apparaît nulle part dans votre devis. Et un gars du livre ne signifie pas qu'il est "largement considérée". Je dirais que l'suivantes: 1) le "Clonable" interface n'est pas prévu pour indiquer qu'une classe possède une méthode clone, ou qu'une classe a tout le comportement du public. Il est mal nommée, car elle pourrait induire les gens en erreur en pensant que. 2) Il n'existe pas d'interface en Java qui indique si une classe peut être cloné. Cependant, il n'y a pas d'interfaces pour beaucoup de choses que vous souhaitez, il y avait. Cela ne signifie pas que c'est une "erreur".
La conception de clone et Clonable n'est pas la principale préoccupation ici, la question est à propos, pourquoi "protégé" (par opposition à la pourquoi pas "public"). Quelle que soit votre réponse, qui devrait également expliquer pourquoi "finaliser" est protégé et pourquoi d'autres méthodes comme "toString" est "public" et non pas "protégé".
personne n'a répondu pourquoi la méthode protégée de la classe d'Objet n'est pas directement accessible par anyclass, comme chaque classe est sous-classe de la classe Object. aussi pourquoi je mandatoryly devez remplacer les Objets de la méthode clone ?
La Clonable interface est tout simplement un marqueur de dire la classe d'appui clone. La méthode est protégé parce que vous ne devriez pas l'appeler sur un objet, vous pouvez (et devriez) override public.
De Soleil:
Dans la classe de l'Objet, la méthode clone() est déclarée protégée. Si tout ce que vous faire est de mettre en œuvre Clonable, seuls les sous-classes et les membres de la même package sera en mesure d'invoquer un clone() sur l'objet. Pour permettre à toute la classe dans un package pour accéder à la méthode clone (), vous aurez à le remplacer et de le déclarer public, comme cela est fait ci-dessous. (Lorsque vous remplacez une méthode, vous pouvez le rendre moins privé, mais pas plus privé. Ici, le protégé méthode clone() dans l'Objet est remplacée comme une méthode publique.)
Ce qui est bien, jusqu'à ce que vous apporter des interfaces dans le mélange, - essayer et tenter de cloner un inconnu de la mise en œuvre de Set
mais peut-être que certaines implémentations de Jeu ne sont pas clonable
Vous ne pouvez pas cloner tout ce qui n'est pas de mettre en œuvre la Clonable interface: c'est un marqueur qui indique que "Cette classe est correctement clonable"--très similaire à l'interface Serializable. Par ailleurs, il y a un moyen de cloner par le biais des classes de sérialisation qui fonctionne bien--google quelque chose comme "la sérialisation java clone" et vous trouverez probablement une poignée de façons d'obtenir une copie de votre objet.
Vous ne pouvez pas cloner tout ce qui n'est pas de mettre en œuvre la Clonable interface, mais juste parce que quelque chose implémente l'Clonable interface ne signifie pas que vous pouvez le cloner.
Votre commentaire est correct, mais si c'était en réponse au commentaire ci-dessus, alors vous pas compris ce que je disais. Une classe qui ne peut pas être cloné, mais peut être sérialisé peut être "cloné" (ou disons simplement copié) par l'intermédiaire de la sérialisation. Cela fait un excellent, bon marché (à code) système de clonage, juste sérialiser un tableau d'octets et de sérialiser sur une autre variable.
K : je n'ai pas le remplacer & accroître la visibilité de logique ici. Si j'ai à régler avec cette explication, voulez-vous de pls en outre expliquer, pourquoi la même chose n'est pas appliquée pour le reste des méthodes (à l'exception de "finalize") ? Dis, pourquoi "toString" n'est pas protégé?
toString a une implémentation par défaut, si vous appelez quelque chose de bon va se passer, et vous obtiendrez une chaîne de caractères. est égal a un défaut de mise en œuvre (le même que ==). Clone ne peut pas avoir un défaut de mise en œuvre. Si vous appelez clone sur un objet qui n'a pas mis en œuvre, vous ne serez pas obtenir un comportement raisonnable. Le clonage est complexe et ne peut pas vraiment être fait automatiquement (certains objets sans les constructeurs par défaut peut être impossible de génériquement clone), donc par défaut qu'ils en font un peu plus sûr. Je pense le mettre sur l'Objet à tous, cependant, n'aurait pas été nécessaire.
clone est protégé, car il est une chose qui devrait être remplacé, de sorte qu'il est spécifique à la classe en cours. Alors qu'il serait possible de créer un public clone méthode de cloner n'importe quel objet, ce ne serait pas aussi bon que d'une méthode écrite spécifiquement pour la classe qui en a besoin.
mais pourquoi doit-elle être protégée pour qui?
Il est protégé de sorte que vous n'utilisez pas l'un dans l'objet (il va juste lancer une exception de toute façon). Ils veulent que vous remplacer dans une classe, puis vous le rendre public. (réponse à quelques reprises ci-dessous aussi)
Et inutile lors de l'examen des interfaces selon mon point de vue ci-dessous
devrait être substituée est pas très clair, alors il doit avoir été abstraite et ne doivent alors pas dans l'Objet de la Classe, je suis en train dur à comprendre pourquoi est-il si.
La méthode Clone ne peut pas être directement utilisé sur n'importe quel objet, c'est pourquoi il est destiné à être remplacée par la sous-classe.
Bien sûr, il pourrait être publique et il suffit de jeter une exception appropriée lorsque le clonage n'est pas possible, mais je pense que ce serait trompeuse.
La façon clone est mis en œuvre dès maintenant vous fait penser à pourquoi vous voulez utiliser clone, et la façon dont vous voulez que votre objet à sélectionner.
Il est protégé, car le défaut de mise en œuvre ne un peu memberwise copie de tous les domaines (y compris privé), contourner constructeur. Ce n'est pas quelque chose d'un objet peut être conçu pour traiter en premier lieu (par exemple, il peut garder une trace de la création des instances de l'objet dans une liste partagée, ou quelque chose de similaire).
Pour la même raison, le défaut de mise en œuvre de clone() va jeter si l'objet, il est appelé à ne pas mettre en œuvre Cloneable. C'est potentiellement un fonctionnement sécuritaire de l'appareil avec de lourdes conséquences, et, par conséquent, l'auteur de la classe doit refuser explicitement dans.
Le défaut de mise en oeuvre (objet) déclenche une exception selon les docs...
Non, il n'est pas de simplement jeter. De son JavaDoc: "La méthode clone pour Objet de classe exécute une opération de clonage. Tout d'abord, si la classe de cet objet n'implémente pas l'interface Clonable, puis un CloneNotSupportedException est levée. Notez que tous les tableaux sont considérés comme implémenter l'interface Clonable. Sinon, cette méthode crée une nouvelle instance de la classe de cet objet et initialise tous ses domaines, avec exactement le contenu du champs correspondants de cet objet, comme si par cession, le contenu de ces champs ne sont pas eux-mêmes cloné."
*By convention, classes that implement thisinterface(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 thisinterface 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 implementsthisinterface.Evenif the clone method is invoked
* reflectively, there is no guarantee that it will succeed.
Ainsi, vous pouvez appeler clone sur chaque objet, mais ce serait vous donner la plupart du temps pas les résultats que vous voulez ou une exception. Mais c'est seulement recommandé si vous implémentez clonable.
Vous pas appel clone sur chaque Objet, parce qu'il est protégé!
Désolé pour mon un peu floues deux dernières phrases...
Méthode Clone() a un contrôle interne "instance de Clonable ou pas".C'est la façon dont Java équipe pourrait pensée va limiter l'utilisation abusive de la méthode clone ().méthode clone() est protégée, c'est à dire accessible par les sous-classes. Puisque l'objet est la classe mère de toutes les sous-classes, de sorte méthode Clone() peut être utilisée par toutes les classes enfait si nous n'avons pas de vérification ci-dessus de "l'instance de Clonable'. C'est la raison pour Java équipe peut avoir pensé à limiter l'utilisation abusive de clone() en ayant la vérification de la méthode clone () "est-ce qu'instance de Clonable'.
Donc quelles que soient les classes d'œuvre clonable pouvez utiliser la méthode clone() de la classe Object.
Aussi, puisqu'elle a fait protégé, il est disponible uniquement aux sous-classes qui implémente clonable interface. Si nous voulons la rendre publique, cette méthode doit être remplacée par la sous-classe avec leur propre mise en œuvre.
Oui, même problème que j'ai rencontré.
Mais je le résoudre par la mise en œuvre de ce code
publicclassSideimplementsCloneable{publicSide clone(){Side side =null;try{
side =(Side)super.clone();}catch(CloneNotSupportedException e){System.err.println(e);}return side;}}
Tout comme le avant que quelqu'un dit.
CloneNotSupportedException est un autre exemple d'un checked exception qui doit être désactivée (qui est, il devrait s'étendre sur RuntimeException, pas d'Exception). Bien que la méthode clone() de la classe Côté implémente Clonable et donc ne jamais jeter CloneNotSupportedException, Côté.clone() doit toujours attraper ou déclarer l'exception. Cela ajoute simplement superflu exception des bruits de manipulation de la méthode clone ().
Bien, aussi, le soleil, les développeurs ne sont que des hommes, et ils n'ont en effet faire une énorme erreur que de mettre en œuvre la méthode clone protégées, la même erreur que pour la mise en œuvre d'un non-fonctionnement de la méthode clone dans ArrayList! Donc, en général, il existe un beaucoup plus profonde incompréhension de même connu des programmeurs Java sur la méthode clone.
Cependant, j'ai récemment trouvé une solution rapide et facile pour copier n'importe quel objet avec l'ensemble de son contenu, peu importe comment il est construit et ce qu'il contient, voir ma réponse ici: Bug dans l'utilisation de l'Objet.clone()
De nouveau, Java JDK cadre montre brillant de la pensée:
Clonable interface ne contient pas de "T public clone();" la méthode, car il agit plus comme un attribut (par exemple. Serializable) qui permet à une instance d'être cloné.
Il n'y a rien de mal avec cette conception parce que:
Objet.clone() ne fera pas ce que vous voulez avec votre personnalisé de classe.
Si vous avez Maclasse implements Clonable => vous écraser clone() avec
"public Maclasse clone()"
Si vous avez MyInterface s'étend Clonable et certains MyClasses la mise en œuvre de MyInterface:
il vous suffit de définir "public MyInterface clone();" dans l'interface et de chaque méthode à l'aide de MyInterface les objets seront en mesure de cloner eux, peu importe leur MyClass de classe.
si votre classe se trouvent être hérité de votre classe dérivée de clone de mise en œuvre ne sera pas en sécurité jusqu'à ce que votre classe de base implémentations de fournir en toute sécurité clone méthodes. Aussi, il est une sorte de conception inhabituelle condition d'avoir une interface sans méthode/attribut. Cette interface n'a pas la force de la classe pour mettre en œuvre clone.
Le fait que le clone est protégé est extrêmement douteuses, comme le fait que le
clone
méthode n'est pas déclarée dans leCloneable
interface.Il rend la méthode assez inutile pour la prise de copies de données, car vous ne pouvez pas dire:
Je pense que la conception de
Cloneable
est maintenant largement considérée comme une erreur (citation ci-dessous). Normalement j'veux être en mesure de faire des implémentations de l'interfaceCloneable
mais pas nécessairement l'interfaceCloneable
(similaire à l'utilisation deSerializable
). Cela ne peut se faire sans réflexion:Serializable
- c'est à implémentations de décider de mettre en œuvreSerializable
. J'ai été l'extension à laCloneable
- il n'est pas quelque chose qui une interface doit s'étendre - mais une mise en œuvre d'une interface est libre d'êtreCloneable
. Le problème est que, si vous avez un paramètre du type d'interface, vous demandez, demandez-lui s'il est clonable; mais alors vous ne pouvez pas cloner!La Clonable interface est tout simplement un marqueur de dire la classe d'appui clone. La méthode est protégé parce que vous ne devriez pas l'appeler sur un objet, vous pouvez (et devriez) override public.
De Soleil:
Dans la classe de l'Objet, la méthode clone() est déclarée protégée. Si tout ce que vous faire est de mettre en œuvre Clonable, seuls les sous-classes et les membres de la même package sera en mesure d'invoquer un clone() sur l'objet. Pour permettre à toute la classe dans un package pour accéder à la méthode clone (), vous aurez à le remplacer et de le déclarer public, comme cela est fait ci-dessous. (Lorsque vous remplacez une méthode, vous pouvez le rendre moins privé, mais pas plus privé. Ici, le protégé méthode clone() dans l'Objet est remplacée comme une méthode publique.)
Set
clone
est protégé, car il est une chose qui devrait être remplacé, de sorte qu'il est spécifique à la classe en cours. Alors qu'il serait possible de créer un publicclone
méthode de cloner n'importe quel objet, ce ne serait pas aussi bon que d'une méthode écrite spécifiquement pour la classe qui en a besoin.La méthode Clone ne peut pas être directement utilisé sur n'importe quel objet, c'est pourquoi il est destiné à être remplacée par la sous-classe.
Bien sûr, il pourrait être publique et il suffit de jeter une exception appropriée lorsque le clonage n'est pas possible, mais je pense que ce serait trompeuse.
La façon clone est mis en œuvre dès maintenant vous fait penser à pourquoi vous voulez utiliser clone, et la façon dont vous voulez que votre objet à sélectionner.
Il est protégé, car le défaut de mise en œuvre ne un peu memberwise copie de tous les domaines (y compris privé), contourner constructeur. Ce n'est pas quelque chose d'un objet peut être conçu pour traiter en premier lieu (par exemple, il peut garder une trace de la création des instances de l'objet dans une liste partagée, ou quelque chose de similaire).
Pour la même raison, le défaut de mise en œuvre de
clone()
va jeter si l'objet, il est appelé à ne pas mettre en œuvreCloneable
. C'est potentiellement un fonctionnement sécuritaire de l'appareil avec de lourdes conséquences, et, par conséquent, l'auteur de la classe doit refuser explicitement dans.De la javadoc de clonable.
Ainsi, vous pouvez appeler clone sur chaque objet, mais ce serait vous donner la plupart du temps pas les résultats que vous voulez ou une exception. Mais c'est seulement recommandé si vous implémentez clonable.
À mon humble avis, c'est aussi simple que cela:
#clone
ne doit pas être appelée sur la non-clonable objets, par conséquent, il n'est pas rendu public#clone
doit être appelé par les sous-classes obObject
que de mettre en œuvre Clonable pour obtenir la copie superficielle de la classe à droiteQuelle est la bonne portée pour les méthodes qui doivent être appelées par des sous-classes, mais pas par les autres classes?
C'est
protected
.Classes de la mise en œuvre de
Cloneable
de rendre cette méthode publique de sorte qu'il peut être appelé à d'autres classes.Méthode Clone() a un contrôle interne "instance de Clonable ou pas".C'est la façon dont Java équipe pourrait pensée va limiter l'utilisation abusive de la méthode clone ().méthode clone() est protégée, c'est à dire accessible par les sous-classes. Puisque l'objet est la classe mère de toutes les sous-classes, de sorte méthode Clone() peut être utilisée par toutes les classes enfait si nous n'avons pas de vérification ci-dessus de "l'instance de Clonable'. C'est la raison pour Java équipe peut avoir pensé à limiter l'utilisation abusive de clone() en ayant la vérification de la méthode clone () "est-ce qu'instance de Clonable'.
Donc quelles que soient les classes d'œuvre clonable pouvez utiliser la méthode clone() de la classe Object.
Aussi, puisqu'elle a fait protégé, il est disponible uniquement aux sous-classes qui implémente clonable interface. Si nous voulons la rendre publique, cette méthode doit être remplacée par la sous-classe avec leur propre mise en œuvre.
Oui, même problème que j'ai rencontré.
Mais je le résoudre par la mise en œuvre de ce code
Tout comme le avant que quelqu'un dit.
Bien, aussi, le soleil, les développeurs ne sont que des hommes, et ils n'ont en effet faire une énorme erreur que de mettre en œuvre la méthode clone protégées, la même erreur que pour la mise en œuvre d'un non-fonctionnement de la méthode clone dans ArrayList! Donc, en général, il existe un beaucoup plus profonde incompréhension de même connu des programmeurs Java sur la méthode clone.
Cependant, j'ai récemment trouvé une solution rapide et facile pour copier n'importe quel objet avec l'ensemble de son contenu, peu importe comment il est construit et ce qu'il contient, voir ma réponse ici: Bug dans l'utilisation de l'Objet.clone()
De nouveau, Java JDK cadre montre brillant de la pensée:
Clonable interface ne contient pas de "T public clone();" la méthode, car il agit plus comme un attribut (par exemple. Serializable) qui permet à une instance d'être cloné.
Il n'y a rien de mal avec cette conception parce que:
Objet.clone() ne fera pas ce que vous voulez avec votre personnalisé de classe.
Si vous avez Maclasse implements Clonable => vous écraser clone() avec
"public Maclasse clone()"
Si vous avez MyInterface s'étend Clonable et certains MyClasses la mise en œuvre de MyInterface:
il vous suffit de définir "public MyInterface clone();" dans l'interface et de chaque méthode à l'aide de MyInterface les objets seront en mesure de cloner eux, peu importe leur MyClass de classe.