En java, il est un peu difficile à mettre en œuvre une fonction de copie d’objet profond. Quelles mesures vous prenez pour s’assurer que l’objet d’origine et celui cloné ne partagent aucune référence ?
Réponses
Trop de publicités?Un moyen sûr est de sérialiser l’objet, puis désérialiser. Ceci assure que tout est une nouvelle référence.
Voici un article sur la façon de le faire efficacement.
Mises en garde : Il est possible pour les classes à substituer la sérialisation telle que les nouvelles instances sont pas créé, par exemple pour les singletons. Aussi cela bien sûr ne fonctionne pas si votre classes ne sont pas Serializable.
Quelques personnes ont mentionné l'aide ou de la transgression de l'Objet.clone(). Ne pas le faire. Objet.clone() a quelques problèmes majeurs, et son utilisation est déconseillée dans la plupart des cas. Veuillez consulter l'Article 11, à partir de "Effective Java" par Joshua Bloch pour une réponse complète. Je crois que vous pouvez utiliser en toute sécurité des Objets.clone() de type primitif, des tableaux, mais en dehors de cela, vous devez être judicieux dans le choix d'utilisation et de primordial clone.
Les systèmes qui s'appuient sur la sérialisation XML (ou autre) sont encombrants.
Il n'y a pas de réponse facile ici. Si vous souhaitez copie en profondeur d'un objet que vous aurez à parcourir le graphe d'objets et de copie de chaque objet enfant explicitement via l'objet du constructeur de copie ou d'un statique méthode de fabrique qui, à son tour profonde des copies de l'objet enfant. Immutables (par exemple des Chaînes de caractères) ne doivent pas être copiés. En aparté, vous devriez favoriser l'immutabilité pour cette raison.
Vous pouvez effectuer une sérialisation de copie complète sans créer de fichiers.
Copie:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(object);
oos.flush();
oos.close();
bos.close();
byte[] byteData = bos.toByteArray();
Restaurer:
ByteArrayInputStream bais = new ByteArrayInputStream(byteData);
(Object) object = (Object) new ObjectInputStream(bais).readObject();
Vous pouvez faire un clone profond basé sur la sérialisation en utilisant org.apache.commons.lang.SerializationUtils.clone () dans Commons Lang, mais soyez prudent - les performances sont abyssales.
En règle générale, il est recommandé d'écrire vos propres méthodes de clonage pour chaque classe d'un objet du graphe d'objet nécessitant un clonage.
Une façon de mettre en œuvre des copie en profondeur est d'ajouter une copie des constructeurs pour chaque classe associée. Un constructeur de copie prend une instance de 'ce' que son seul argument et des copies de toutes les valeurs. Assez peu de travail, mais assez simple et sûre.
EDIT: notez que vous n'avez pas besoin d'utiliser des méthodes accesseur pour lire les champs. Vous pouvez accéder à toutes les zones directement parce que la source de l'instance est toujours du même type que l'instance avec le constructeur de copie. Évident, mais peut être négligé.
Exemple:
public class Order {
private long number;
public Order() {
}
/**
* Copy constructor
*/
public Order(Order source) {
number = source.number;
}
}
public class Customer {
private String name;
private List<Order> orders = new ArrayList<Order>();
public Customer() {
}
/**
* Copy constructor
*/
public Customer(Customer source) {
name = source.name;
for (Order sourceOrder : source.orders) {
orders.add(new Order(sourceOrder));
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Edit: Notez que lors de l'utilisation de copier les constructeurs vous avez besoin de savoir l'exécution type de l'objet que vous copiez. Avec l'approche ci-dessus vous ne pouvez pas copier facilement une liste mélangée (vous pourriez être en mesure de le faire avec un peu de réflexion code).