Méthode de clonage vs. constructeur de copie en java. quelle est la solution correcte ? où utiliser chaque cas ?
Réponses
Trop de publicités?Clone est cassé, donc ne l'utilisez pas.
LA MÉTHODE CLONE de la classe des objets est une méthode quelque peu magique qui fait ce qu'aucune méthode Java pure ne pourrait jamais faire : Elle produit une copie identique de son objet. Elle est présente dans la superclasse superclasse Object primordiale depuis les Beta-release de Java et, comme toute magie ancienne, elle nécessite la magie ancienne, nécessite les incantation appropriée pour empêcher le sort de se retourner contre lui de manière inattendue
Préférez une méthode qui copie l'objet
Foo copyFoo (Foo foo){
Foo f = new Foo();
//for all properties in FOo
f.set(foo.get());
return f;
}
Lire la suite http://adtmag.com/articles/2000/01/18/effective-javaeffective-cloning.aspx
Gardez à l'esprit que clone()
ne fonctionne pas en dehors de la boîte. Vous devrez mettre en œuvre Cloneable
et remplacer le clone()
méthode de fabrication dans public
.
Il existe quelques solutions de rechange, qui sont préférables (étant donné que les clone()
présente de nombreux problèmes de conception, comme indiqué dans d'autres réponses), et le constructeur de copies nécessiterait un travail manuel :
-
BeanUtils.cloneBean(original)
crée un clone peu profond, comme celui créé parObject.clone()
. (cette classe est de commons-beanutils ) -
SerializationUtils.clone(original)
crée un clone profond. (c'est-à-dire que tout le graphe de propriétés est cloné, pas seulement le premier niveau) (de commons-lang ), mais toutes les classes doivent implémenterSerializable
-
Bibliothèque Java de clonage profond offre un clonage profond sans avoir à mettre en œuvre
Serializable
Clone() a été conçu avec plusieurs erreurs (cf. cette question ), il est donc préférable de l'éviter.
De Java efficace 2ème édition Point 11 : Contourner le clone de manière judicieuse.
Compte tenu de tous les problèmes associés à Cloneable, on peut dire que que les autres interfaces ne devraient pas l'étendre, et que les classes conçues pour l'héritage (point 17) ne devraient pas l'implémenter. En raison de ses nombreux défauts, certains programmeurs experts choisissent tout simplement de ne jamais de ne jamais surcharger la méthode clone et de ne jamais l'invoquer sauf, peut-être, pour copier des tableaux. Si vous concevez une classe pour l'héritage, soyez conscient que si vous choisissez de ne pas fournir une méthode clone protégée bien conçue, il sera protégées, il sera impossible pour les sous-classes d'implémenter Cloneable.
Ce livre décrit également les nombreux avantages des constructeurs de copies par rapport à Cloneable/clone.
- Ils ne s'appuient pas sur un mécanisme de création d'objets extralinguistiques à risque.
- Ils n'exigent pas une adhésion inapplicable à des conventions peu documentées.
- Ils n'entrent pas en conflit avec l'utilisation correcte des champs finaux.
- Ils ne lèvent pas d'exceptions vérifiées inutiles
- Ils n'ont pas besoin de plâtres.
Toutes les collections standard ont des constructeurs de copie. Utilisez-les.
List<Double> original = // some list
List<Double> copy = new ArrayList<Double>(original);
Gardez à l'esprit que le constructeur de copie limite le type de la classe à celui du constructeur de copie. Prenons l'exemple suivant :
// Need to clone person, which is type Person
Person clone = new Person(person);
Cela ne fonctionne pas si person
pourrait être une sous-classe de Person
(ou si Person
est une interface). C'est là tout l'intérêt de clone, qui permet de cloner le bon type dynamiquement au moment de l'exécution (en supposant que clone soit correctement implémenté).
Person clone = (Person)person.clone();
ou
Person clone = (Person)SomeCloneUtil.clone(person); // See Bozho's answer
Maintenant person
peut être n'importe quel type de Person
en supposant que clone
est correctement mis en œuvre.
Voir aussi : Comment remplacer correctement la méthode clone ? . Le clonage est cassé en Java, c'est si difficile pour le faire correctement, et même quand il le fait. n'offre pas vraiment beaucoup donc ça ne vaut pas vraiment la peine de s'embêter.