Nous savons que cette interface Cloneable existe en Java. Les classes qui implémentent cette interface auront la possibilité d'être copiées. En même temps, la copie s'effectue en mémoire, c'est plus rapide que la génération directe d'objets via. nouveau, notamment dans la génération de gros objets, l'amélioration des performances est très évidente. Cependant, nous savons que la copie est divisée en copie profonde et copie superficielle, mais la copie superficielle présente le problème d'une copie incomplète des attributs de l'objet. Concernant la copie profonde et la copie superficielle, veuillez vous référer ici : Analyse progressive de la copie superficielle et de la copie profonde de Java
1. Problème de copie superficielle
Regardons d'abord le code suivant :
public class Person implements Cloneable{ /** 姓名 **/ private String name; /** 电子邮件 **/ private Email email; public String getName() { return name; } public void setName(String name) { this.name = name; } public Email getEmail() { return email; } public void setEmail(Email email) { this.email = email; } public Person(String name,Email email){ this.name = name; this.email = email; } public Person(String name){ this.name = name; } protected Person clone() { Person person = null; try { person = (Person) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return person; } } public class Client { public static void main(String[] args) { //写封邮件 Email email = new Email("请参加会议","请与今天12:30到二会议室参加会议..."); Person person1 = new Person("张三",email); Person person2 = person1.clone(); person2.setName("李四"); Person person3 = person1.clone(); person3.setName("王五"); System.out.println(person1.getName() + "的邮件内容是:" + person1.getEmail().getContent()); System.out.println(person2.getName() + "的邮件内容是:" + person2.getEmail().getContent()); System.out.println(person3.getName() + "的邮件内容是:" + person3.getEmail().getContent()); } } -------------------- Output: 张三的邮件内容是:请与今天12:30到二会议室参加会议... 李四的邮件内容是:请与今天12:30到二会议室参加会议... 王五的邮件内容是:请与今天12:30到二会议室参加会议...
Dans cette application, définissez d'abord un e-mail, puis envoyez l'e-mail à Zhang San, Li Si et Wang Wu. Puisqu'ils utilisent le même e-mail et n'ont que des noms différents, utilisez la classe d'objet de Zhang San. les objets John Four et Wang Five, puis changez le nom. Il n'y a rien de mal avec le programme jusqu'à présent, mais si nous avons besoin que Zhang San arrive 30 minutes à l'avance, nous modifierons le contenu de l'e-mail :
public class Client { public static void main(String[] args) { //写封邮件 Email email = new Email("请参加会议","请与今天12:30到二会议室参加会议..."); Person person1 = new Person("张三",email); Person person2 = person1.clone(); person2.setName("李四"); Person person3 = person1.clone(); person3.setName("王五"); person1.getEmail().setContent("请与今天12:00到二会议室参加会议..."); System.out.println(person1.getName() + "的邮件内容是:" + person1.getEmail().getContent()); System.out.println(person2.getName() + "的邮件内容是:" + person2.getEmail().getContent()); System.out.println(person3.getName() + "的邮件内容是:" + person3.getEmail().getContent()); } }
Ici, nous utilisons également l'objet de Zhang San a réalisé la communication entre Li Si et Li Si. Wang Wu a copié et a finalement modifié le contenu de l'e-mail de Zhang San comme suit : Veuillez vous rendre dans la deuxième salle de conférence à midi aujourd'hui pour assister à la réunion... Mais le résultat est le suivant :
张三的邮件内容是:请与今天12:00到二会议室参加会议... 李四的邮件内容是:请与今天12:00到二会议室参加会议... 王五的邮件内容是:请与今天12:00到二会议室参加会议...
Ici, on se demande pourquoi le contenu des emails de Li Si et Wang Wu a également été modifié ? Il y aura des objections si on leur demande d’arriver 30 minutes plus tôt !
En fait, la clé du problème réside dans la méthode clone(). Nous savons que la méthode clone() utilise la méthode clone() de la classe Object, mais cette méthode a un défaut. ne copie pas tous les attributs de l'objet, mais copiés de manière sélective. Les règles de base sont les suivantes :
1. Type de base
Si la variable est un type de base, copiez sa valeur, telle que int, flottez, attendez.
2. Objet
Si la variable est un objet d'instance, copiez sa référence d'adresse, ce qui signifie que le nouvel objet et l'objet d'origine partagent la variable d'instance.
3. String
Si la variable est une chaîne, copiez sa référence d'adresse. Mais une fois modifié, il régénérera une nouvelle chaîne à partir du pool de chaînes et l'objet Ziducheng d'origine restera inchangé.
Sur la base des règles ci-dessus, nous pouvons facilement trouver le problème. Les trois partagent un objet commun. Si Zhang San modifie le contenu de l'e-mail, Li Si et Wang Wu le modifieront également, donc le ci-dessus apparaît. Nous pouvons encore résoudre cette situation. Il nous suffit de créer un nouvel objet dans la méthode clone(), puis Zhang San fait référence à l'objet :
protected Person clone() { Person person = null; try { person = (Person) super.clone(); person.setEmail(new Email(person.getEmail().getObject(),person.getEmail().getContent())); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return person; }
Donc : la copie superficielle est juste un type fourni par Java. Mécanisme de copie simple, pas facile à utiliser directement.
Il y a toujours un problème avec la solution ci-dessus. S'il y a un grand nombre d'objets dans notre système qui sont générés par copie, si nous écrivons une méthode clone() pour chaque classe, des copies complètes le seront également. requis. , créez un grand nombre de nouveaux objets, ce projet est très volumineux, ici nous pouvons utiliser la sérialisation pour copier les objets.
2. Utiliser la sérialisation pour copier des objets
Comment utiliser la sérialisation pour copier des objets ? C'est relativement facile à réaliser en copiant le flux d'octets en mémoire. Écrivez l'objet parent dans un flux d'octets, puis lisez-le à partir du flux d'octets, afin que vous puissiez créer un nouvel objet et qu'il n'y ait aucun problème de partage de référence entre le nouvel objet et l'objet parent. Implémentez réellement une copie complète de. objets.
public class CloneUtils { @SuppressWarnings("unchecked") public static <T extends Serializable> T clone(T obj){ T cloneObj = null; try { //写入字节流 ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream obs = new ObjectOutputStream(out); obs.writeObject(obj); obs.close(); //分配内存,写入原始对象,生成新对象 ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray()); ObjectInputStream ois = new ObjectInputStream(ios); //返回生成的新对象 cloneObj = (T) ois.readObject(); ois.close(); } catch (Exception e) { e.printStackTrace(); } return cloneObj; } }
Les objets utilisant cette classe d'outils doivent implémenter l'interface Serialisable, sinon il n'y a aucun moyen de réaliser le clonage.
public class Person implements Serializable{ private static final long serialVersionUID = 2631590509760908280L; .................. //去除clone()方法 } public class Email implements Serializable{ private static final long serialVersionUID = 1267293988171991494L; .................... }
Par conséquent, les objets utilisant cette classe d'outils peuvent réaliser le clonage d'objets tant qu'ils implémentent l'interface Serialisable, et il n'est pas nécessaire d'hériter de l'interface Cloneable pour implémenter la méthode clone().
public class Client { public static void main(String[] args) { //写封邮件 Email email = new Email("请参加会议","请与今天12:30到二会议室参加会议..."); Person person1 = new Person("张三",email); Person person2 = CloneUtils.clone(person1); person2.setName("李四"); Person person3 = CloneUtils.clone(person1); person3.setName("王五"); person1.getEmail().setContent("请与今天12:00到二会议室参加会议..."); System.out.println(person1.getName() + "的邮件内容是:" + person1.getEmail().getContent()); System.out.println(person2.getName() + "的邮件内容是:" + person2.getEmail().getContent()); System.out.println(person3.getName() + "的邮件内容是:" + person3.getEmail().getContent()); } } ------------------- Output: 张三的邮件内容是:请与今天12:00到二会议室参加会议... 李四的邮件内容是:请与今天12:30到二会议室参加会议... 王五的邮件内容是:请与今天12:30到二会议室参加会议...
Ce qui précède est le contenu de la partie 5 de l'amélioration Java -----Utilisation de la sérialisation pour copier des objets Pour plus de contenu connexe, veuillez prêter attention au site Web PHP chinois (www.php.cn). !