72 votes

Recommandation d'utilitaire de clonage profond

Existe-t-il une utilité pour le clonage en profondeur des collections Java

  • Tableaux
  • Des listes
  • Plans

REMARQUE: préférez une solution sans utiliser la sérialisation, mais avec la méthode Object.clone (). Je peux être sûr que mon objet personnalisé implémentera la méthode clone () et utilisera uniquement les classes java-standard qui sont clonables ...

65voto

Cojones Points 1006

Je pense que la précédente verts de réponse était mauvaise , pourquoi me demanderez-vous?

  • Il ajoute beaucoup de code
  • Il exige de vous à la liste de tous les champs à copier et de le faire
  • Cela ne fonctionnera pas pour les Listes lors de l'utilisation de clone() (C'est ce que clone() pour HashMap dit: Retourne une copie de cette table de hachage exemple: les touches et valuesthemselves ne sont pas dupliqués.) donc, vous vous retrouvez de le faire manuellement (ce qui me fait pleurer)

Oh, et par la manière, la sérialisation est aussi mauvais, vous pourriez avoir à ajouter Serializable tous sur la place (ce qui me fait aussi pleurer).

Quelle est donc la solution:

Java Profonde-Clonage de la bibliothèque Le clonage de la bibliothèque est un petit open source (licence apache) bibliothèque java qui profonde clones objets. Les objets n'ont pas à mettre en œuvre les Clonable interface. Effectivelly, cette bibliothèque peut cloner un des objets java. Il peut être utilisé à-d. dans les implémentations de cache si vous ne voulez pas l'objet mis en cache à être modifiés ou chaque fois que vous voulez créer une copie en profondeur des objets.

Cloner cloner=new Cloner();
XX clone = cloner.deepClone(someObjectOfTypeXX);

Consultez-le à l' http://code.google.com/p/cloning/

20voto

Aaron Digulla Points 143830

Toutes les approches pour copier des objets en Java ont de sérieux problèmes:

Clone

  1. La méthode clone() est protégé, de sorte que vous ne pouvez pas l'appeler directement, à moins que la classe en question la remplace avec une méthode publique.
  2. clone() n'appelle pas le constructeur. De tout constructeur. Il va allouer de la mémoire, d'attribuer à l'interne class domaine (que vous pouvez lire via getClass()) et de copier les domaines de l'original.

Pour des problèmes plus avec le clone(), voir le point 11 de Joshua Bloch du livre "Effective Java, Deuxième Édition"

Sérialiser

Sérialiser est encore pire; il a beaucoup de défauts, clone() et puis certains. Josué a un chapitre entier avec quatre points pour ce seul sujet.

Ma Solution

Ma solution est d'ajouter une nouvelle interface pour mes projets:

public interface Copyable<T> {
    T copy ();
    T createForCopy ();
    void copyTo (T dest);
}

Le code ressemble à ceci:

class Demo implements Copyable<Demo> {
    public Demo copy () {
        Demo copy = createForCopy ();
        copyTo (copy);
        return copy;
    }
    public void createForCopy () {
        return new Demo ();
    }
    public void copyTo (Demo dest)
        super.copyTo (dest);
        ...copy fields of Demo here...
    }
}

Malheureusement, j'ai copier ce code à tous mes objets, mais c'est toujours le même code, si je peux utiliser une Éclipse de l'éditeur de modèle. Avantages:

  1. Je peux décider quel constructeur à appeler et comment initialiser le champ.
  2. L'initialisation se passe dans un déterministe de l'ordre (de la racine de la classe à la classe d'instance)
  3. Je peux réutiliser les objets existants et les remplacer
  4. Type de coffre-fort
  5. Les Singletons séjour singletons

Pour les types standards Java (comme les collections, etc), j'utilise une classe utilitaire qui peut copier ceux-ci. Les méthodes ont des drapeaux et des rappels, afin que je puisse contrôler la profondeur de la copie devrait être.

17voto

Brad Cupit Points 2808

Peu profondes, le clonage d'une collection est facile, mais si vous voulez profonde clone, une bibliothèque sera sans doute peut-on faire mieux que le codage à la main (puisque vous voulez cloner les éléments à l'intérieur de la collection).

Tout comme cette réponse, j'ai utilisé le Cloneur de la bibliothèque et plus précisément de la performance testée sur XStream (qui peut "cloner" par la sérialisation puis la désérialisation) et la sérialisation binaire. Si XStream est très rapide à la sérialisation/à partir de xml, Cloner est beaucoup plus rapide au clonage:

0.0851 ms : xstream (clone par la sérialisation/désérialisation)
0.0223 ms : la sérialisation binaire (clone par la sérialisation/désérialisation)
0.0017 ms : cloner
* temps moyen de cloner un objet simple (deux champs) et pas de défaut, constructeur public. Exécuter de 10 000 fois.

En plus d'être rapide, voici d'autres raisons de choisir cloner:

  1. effectue une profonde clone de n'importe quel objet (même ceux dont vous n'avez pas l'écrire vous-même)
  2. vous n'avez pas à garder votre méthode clone() à jour chaque fois que vous ajoutez un champ
  3. vous pouvez cloner des objets qui n'ont pas de constructeur public par défaut
  4. fonctionne avec le Printemps
  5. (optimisation) n'est pas clone connue des objets immuables (comme Integer, String, etc.)
  6. facile à utiliser. Exemple:

    cloner.deepClone(anyObject);

14voto

Je suis le créateur de la cloner lib, celui que Brad présenté. C'est une solution pour le clonage des objets sans avoir à écrire de code supplémentaire (pas besoin d'objets sérialisables ou impl méthode clone ())

C'est assez vite dit Brad, et récemment, j'ai téléchargé une version qui est encore plus rapide. Notez que manuellement la mise en œuvre d'une méthode clone() sera plus rapide que clone lib, mais encore une fois, vous aurez besoin d'écrire beaucoup de code.

Cloner lib a très bien fonctionné pour moi, depuis que je l'utilise dans une cache de la mise en œuvre d'un site avec un trafic très lourd (~1 million de demandes/jour). Le cache doit clone environ 10 objets par demande. Il est tout à fait fiable et stable. Mais s'il vous plaît être conscient que le clonage n'est pas sans risque. La lib peut être configuré pour println chaque instance de la classe qu'elle clones au cours de dev. De cette façon, vous pouvez vérifier si elle clones que vous pensez qu'il faut cloner - graphes d'objets peut être très profond et peut contenir des références à une surprenante grande quantité d'objets. Avec clone lib, vous pouvez le demander à ne pas cloner les objets que vous ne voulez pas, c'est à dire des singletons.

10voto

John Feminella Points 116878

D'une manière générale profonde clone une collection arbitraire est de sérialiser un ruisseau, puis le lire dans une nouvelle collection. Vous serez réhydrater complètement nouveaux objets qui n'ont pas de relation avec les grands anciens, d'autres que d'être des copies identiques.

Découvrez Bruno réponse d'un lien vers le Apache Commons sérialisation des classes utilitaires, ce qui sera très utile si c'est le chemin que vous décidez de prendre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X