Comment faire pour Faire une Copie d’un Objet en Java

Introduction

Lorsque l’on veut copier un objet en Java, il y a deux possibilités que nous avons besoin de prendre en considération — en une copie et une copie en profondeur.

la copie superficielle est l’approche lorsque nous ne copions que des valeurs de champ et que la copie peut donc dépendre de l’objet d’origine. Dans l’approche deep copy, nous nous assurons que tous les objets de l’arborescence sont copiés en profondeur, de sorte que la copie ne dépend d’aucun objet existant antérieur qui pourrait changer.,

dans cet article, nous allons comparer ces deux approches et apprendre quatre méthodes pour implémenter la copie profonde.

pour en savoir plus:

Java copy Constructor

Voici comment créer des constructeurs de copie en Java et pourquoi implémenter Cloneable n’est pas une si bonne idée.
en Lire plus →

la Copie de Jeux en Java

Apprendre plusieurs façons comment copier un Jeu en Java.,
Lire la suite →

copier un HashMap en Java

apprenez diverses techniques pour faire des copies superficielles et profondes du HashMap de Java
Lire la suite →

configuration Maven

Nous utiliserons trois dépendances Maven — Gson, Jackson et Apache commons lang — pour tester différentes façons d’effectuer une copie profonde.

ajoutons ces dépendances à notre pom.xml:

Les dernières versions de Gson, Jackson et Apache Commons Lang se trouvent sur Maven Central.,

Modèle

Pour comparer les différentes méthodes pour copier des objets Java, nous avons besoin de deux classes pour travailler sur:

class Address { private String street; private String city; private String country; // standard constructors, getters and setters}
class User { private String firstName; private String lastName; private Address address; // standard constructors, getters and setters}

Copie

Une copie est celui dans lequel nous seulement copier les valeurs des champs d’un objet à un autre:

Dans ce cas h != shallowCopy, ce qui signifie que ce sont des objets différents, mais le problème est que lorsque nous modifions l’une des propriétés de l’adresse d’origine, cela affectera également l’adresse de shallowCopy.,

nous ne nous en préoccuperions pas si L’adresse était immuable, mais ce n’est pas le cas:

Deep Copy

Une copie profonde est une alternative qui résout ce problème. Son avantage est qu’au moins chaque objet mutable dans le graphe d’objet est copié récursivement.

puisque la copie ne dépend d’aucun objet mutable créé précédemment, elle ne sera pas modifiée par accident comme nous l’avons vu avec la copie peu profonde.

dans les sections suivantes, nous montrerons plusieurs implémentations deep copy et démontrerons cet avantage.

5.1., Copy Constructor

la première implémentation que nous allons implémenter est basée sur les constructeurs copy:

public Address(Address that) { this(that.getStreet(), that.getCity(), that.getCountry());}
public User(User that) { this(that.getFirstName(), that.getLastName(), new Address(that.getAddress()));}

dans l’implémentation ci-dessus de la copie profonde, nous n’avons pas créé de nouvelles chaînes dans notre constructeur copy car String est une classe immuable.

en conséquence, ils ne peuvent pas être modifiés par accident. Voyons si cela fonctionne:

5.2. Interface clonable

la deuxième implémentation est basée sur la méthode clone héritée D’Object. Il est protégé, mais nous devons le remplacer comme public.,

nous allons également ajouter une interface de marqueur, Cloneable, aux classes pour indiquer que les classes sont réellement clonables.

ajoutons la méthode clone() de la classe d’Adresse:

Et maintenant, nous allons mettre en œuvre clone() de la classe d’Utilisateur:

Notez que le super.clone () call renvoie une copie superficielle d’un objet, mais nous définissons manuellement des copies profondes des champs mutables, donc le résultat est correct:

bibliothèques externes

Les exemples ci-dessus semblent faciles, mais parfois ils ne s’appliquent pas comme solution lorsque nous ne pouvons pas ajouter un constructeur supplémentaire ou remplacer la méthode clone.,

cela peut se produire lorsque nous ne possédons pas le code, ou lorsque le graphe objet est si compliqué que nous ne terminerions pas notre projet à temps si nous nous concentrions sur l’écriture de constructeurs supplémentaires ou l’implémentation de la méthode clone sur toutes les classes du graphe objet.

alors, Quoi? Dans ce cas, nous pouvons utiliser une bibliothèque externe. Pour obtenir une copie profonde, nous pouvons sérialiser un objet, puis le désérialiser en un nouvel objet.

regardons quelques exemples.

6.1., Apache Commons Lang

Apache Commons Lang a SerializationUtils#clone, qui effectue une copie profonde lorsque toutes les classes du graphe objet implémentent l’interface sérialisable.

Si la méthode rencontre une classe qui n’est pas sérialisable, elle échouera et lancera une SerializationException non cochée.

pour cette raison, nous devons ajouter l’interface sérialisable à nos classes:

6.2. Sérialisation JSON avec Gson

l’autre façon de sérialiser est d’utiliser la sérialisation JSON. Gson est une bibliothèque utilisée pour convertir des objets en JSON et vice versa.,

contrairement à Apache Commons Lang, GSON n’a pas besoin de L’interface sérialisable pour effectuer les conversions.

jetons un coup d’oeil à un exemple:

6.3. Sérialisation JSON avec Jackson

Jackson est une autre bibliothèque qui prend en charge la sérialisation JSON. Cette implémentation sera très similaire à celle utilisant Gson, mais nous devons ajouter le constructeur par défaut à nos classes.

voyons un exemple:

Conclusion

quelle implémentation devrions-nous utiliser pour faire une copie profonde?, La décision finale dépendra souvent des classes que nous allons copier et si nous possédons les classes dans le graphique d’objet.

Comme toujours, les exemples de code complets pour ce tutoriel peuvent être trouvés sur GitHub.

Get a commencé avec le Printemps 5 et le Printemps de Démarrage 2, par l’intermédiaire de l’Apprendre Printemps cours:

>> découvrez LE PARCOURS

Author: admin

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *