méthode de clonage vs constructeur de copie en Java. lequel est la solution correcte. Où utiliser chaque cas?
Le clone est cassé, alors ne l'utilisez pas.
THE CLONE METHOD de la classe Object est une méthode quelque peu magique qui fait ce qu'aucune méthode pure Java _ ne pourrait jamais faire: elle produit une copie identique de son objet. Il est présent dans la super classe primordiale Object depuis les jours de la version bêta du compilateur Java *; et, comme toute magie ancienne, nécessite l'incantation appropriée pour empêcher le sort de se retourner de façon inattendue.
Préfère 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;
}
En savoir plus http://adtmag.com/articles/2000/01/18/effective-javaeffective-cloning.aspx
N'oubliez pas que clone()
ne fonctionne pas immédiatement. Vous devrez implémenter Cloneable
et écraser la méthode clone()
dans public
.
Quelques alternatives sont préférables (car la méthode clone()
soulève de nombreux problèmes de conception, comme indiqué dans d'autres réponses), et le constructeur de copie nécessiterait un travail manuel:
BeanUtils.cloneBean(original)
crée un clone superficiel, semblable à celui créé par Object.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émenter Serializable
Java Deep Cloning Library offre un clonage profond sans qu'il soit nécessaire de mettre en œuvre Serializable
clone () a été conçu avec plusieurs erreurs (voir cette question ), il est donc préférable de l'éviter.
De Effective Java 2nd Edition , élément 11: Remplacer le clone judicieusement
Compte tenu de tous les problèmes associés à Cloneable, il est prudent de dire que les autres interfaces ne doivent pas l’étendre et que les classes conçues pour l’héritage (élément 17) ne doivent pas l’appliquer. En raison de ses nombreuses faiblesses, certains programmeurs experts choisissent simplement de ne jamais remplacer la méthode de clonage et de ne jamais l'invoquer, à l'exception peut-être de la copie de tableaux. Si vous concevez une classe pour l'héritage, sachez que si vous choisissez de ne pas fournir une méthode de clonage protégé bien comportée, il sera impossible pour les sous-classes d'implémenter Cloneable.
Ce livre décrit également les nombreux avantages des constructeurs de copie sur Cloneable/clone.
Toutes les collections standard ont des constructeurs de copie. Utilise les.
List<Double> original = // some list
List<Double> copy = new ArrayList<Double>(original);
N'oubliez pas que le constructeur de copie limite le type de classe à celui du constructeur de copie. Considérons l'exemple:
// 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’intérêt du clone, c’est qu’il peut peut cloner le bon type de manière dynamique au moment de l’exécution (en supposant que le clone est 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 implémenté.
Voir aussi: Comment remplacer correctement la méthode de clonage? . Le clonage est interrompu en Java, il est si difficile de bien faire les choses, et même s'il le fait ne fonctionne pas offre vraiment beaucoup , donc ça ne vaut pas vraiment la peine.
Grande tristesse: ni clonable/clone ni un constructeur ne sont d'excellentes solutions: JE NE VEUX PAS CONNAÎTRE LA CLASSE D'EXÉCUTION !!! (Par exemple, j'ai une carte que je veux copier, en utilisant la même implémentation cachée de MumbleMap). Je veux juste en faire une copie, si cela est pris en charge. Mais, hélas, Cloneable n’a pas la méthode de clonage dessus, il n’existe donc aucun élément vers lequel vous pouvez taper en toute sécurité sur lequel appeler clone ().
Quelle que soit la meilleure bibliothèque de "copie d'objet" existante, Oracle devrait en faire un composant standard de la prochaine version Java (à moins qu'elle ne le soit déjà, cachée quelque part).
Bien sûr, si davantage de bibliothèques (par exemple - Collections) étaient immuables, cette tâche de "copie" disparaîtrait. Mais ensuite, nous commencerions à concevoir Java des programmes avec des éléments tels que des "invariants de classe" plutôt que le modèle "bean" de verdammt (créer un objet cassé et le muter jusqu'à ce qu'il soit correct [assez]).