使用序列化实现对象的拷贝(转载)

文章出处:http://www.cnblogs.com/chenssy/p/3382979.html

实现Cloneable接口:实现该接口的类都会具备被拷贝的能力,同时拷贝是在内存中进行,在性能方面比我们直接通过new生成对象来的快,特别是在大对象的生成上,使得性能的提升非常明显。

 

 1 package com.itinfo.depthcopy;
 2 
 3 /**
 4  * @author Wáng Chéng Dá
 5  * @create 2017-02-24 9:14
 6  */
 7 public class Email {
 8 
 9     private String type;
10     private String content;
11 
12     public Email(String content) {
13         this.content = content;
14     }
15 
16     public Email(String type, String content) {
17         this.type = type;
18         this.content = content;
19     }
20 
21     public Email() {
22     }
23 
24     public String getType() {
25         return type;
26     }
27 
28     public void setType(String type) {
29         this.type = type;
30     }
31 
32     public String getContent() {
33         return content;
34     }
35 
36     public void setContent(String content) {
37         this.content = content;
38     }
39 
40     @Override
41     public String toString() {
42         return "Email{" +
43                 "type='" + type + '\'' +
44                 ", content='" + content + '\'' +
45                 '}';
46     }
47 
48 }

 

浅拷贝:

 1 package com.itinfo.depthcopy;
 2 
 3 /**
 4  * 实体类
 5  *
 6  * @author Wáng Chéng Dá
 7  * @create 2017-02-24 14:53
 8  */
 9 public class Person implements Cloneable {
10 
11     /** 姓名 **/
12     private String name;
13 
14     /** 电子邮件 **/
15     private Email email;
16 
17     public Person() {
18     }
19 
20     public Person(String name, Email email) {
21         this.name = name;
22         this.email = email;
23     }
24 
25     public Person(String name) {
26         this.name = name;
27     }
28 
29     public String getName() {
30         return name;
31     }
32 
33     public void setName(String name) {
34         this.name = name;
35     }
36 
37     public Email getEmail() {
38         return email;
39     }
40 
41     public void setEmail(Email email) {
42         this.email = email;
43     }
44 
45     protected Person clone() {
46         Person person = null;
47         try {
48             person = (Person)super.clone();
49 //            person.setEmail(new Email(person.getEmail().getType(),person.getEmail().getContent()));//在堆内存中重新分配一块内存存放新生成的email,给属性赋值
50         }catch (CloneNotSupportedException e) {
51             e.printStackTrace();
52         }
53         return person;
54     }
55 }
 1 package com.itinfo.depthcopy;
 2 
 3 /**
 4  * 深拷贝测试
 5  *
 6  * @author Wáng Chéng Dá
 7  * @create 2017-02-24 9:12
 8  */
 9 public class Client {
10     public static void main(String[] args) {
11         //写封邮件
12         Email email = new Email("请参加会议","请与今天12:30到二会议室参加会议...");
13 
14         Person person1 =  new Person("张三",email);
15 
16         Person person2 =  person1.clone();
17         person2.setName("李四");
18         Person person3 =  person1.clone();
19         person3.setName("王五");
20 
21         System.out.println(person1.getName() + "的邮件内容是:" + person1.getEmail().getContent());
22         System.out.println(person2.getName() + "的邮件内容是:" + person2.getEmail().getContent());
23         System.out.println(person3.getName() + "的邮件内容是:" + person3.getEmail().getContent());
24 
25         person1.getEmail().setContent("请与今天12:00到二会议室参加会议...");
26 
27         System.out.println("------------修改张三的邮件内容-------------");
28 
29         System.out.println(person1.getName() + "的邮件内容是:" + person1.getEmail().getContent());
30         System.out.println(person2.getName() + "的邮件内容是:" + person2.getEmail().getContent());
31         System.out.println(person3.getName() + "的邮件内容是:" + person3.getEmail().getContent());
32     }
33 }

  

控制台输出:

张三的邮件内容是:请与今天12:30到二会议室参加会议...
李四的邮件内容是:请与今天12:30到二会议室参加会议...
王五的邮件内容是:请与今天12:30到二会议室参加会议...
------------修改张三的邮件内容-------------
张三的邮件内容是:请与今天12:00到二会议室参加会议...
李四的邮件内容是:请与今天12:00到二会议室参加会议...
王五的邮件内容是:请与今天12:00到二会议室参加会议...

 

深拷贝:

把Person中的 person.setEmail(new Email(person.getEmail().getType(),person.getEmail().getContent())); 注释放开。

 

控制台输出:

张三的邮件内容是:请与今天12:30到二会议室参加会议...
李四的邮件内容是:请与今天12:30到二会议室参加会议...
王五的邮件内容是:请与今天12:30到二会议室参加会议...
------------修改张三的邮件内容-------------
张三的邮件内容是:请与今天12:00到二会议室参加会议...
李四的邮件内容是:请与今天12:30到二会议室参加会议...
王五的邮件内容是:请与今天12:30到二会议室参加会议...

 

利用序列化实现对象的拷贝:

       如何利用序列化来完成对象的拷贝呢?在内存中通过字节流的拷贝是比较容易实现的。把母对象写入到一个字节流中,再从字节流中将其读出来,这样就可以创建一个新的对象了,并且该新对象与母对象之间并不存在引用共享的问题,真正实现对象的深拷贝。

 1 package com.itinfo.IOcopy;
 2 
 3 import java.io.*;
 4 
 5 /**
 6  * IO序列化拷贝
 7  *
 8  * @author Wáng Chéng Dá
 9  * @create 2017-02-24 15:23
10  */
11 public class CloneUtils {
12     @SuppressWarnings("unchecked")
13     public static <T extends Serializable> T clone(T obj){
14         T cloneObj = null;
15         try {
16             //写入字节流
17             ByteArrayOutputStream out = new ByteArrayOutputStream();
18             ObjectOutputStream obs = new ObjectOutputStream(out);
19             obs.writeObject(obj);
20             obs.close();
21 
22             //分配内存,写入原始对象,生成新对象
23             ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
24             ObjectInputStream ois = new ObjectInputStream(ios);
25             //返回生成的新对象
26             cloneObj = (T) ois.readObject();
27             ois.close();
28         } catch (Exception e) {
29             e.printStackTrace();
30         }
31         return cloneObj;
32     }
33 }

 

使用该工具类的对象必须要实现Serializable接口,否则是没有办法实现克隆的。

 1 package com.itinfo.IOcopy;
 2 
 3 
 4 import java.io.Serializable;
 5 
 6 /**
 7  * 实体类
 8  *
 9  * @author Wáng Chéng Dá
10  * @create 2017-02-24 14:53
11  */
12 public class Person implements Serializable {
13 
14     private static final long serialVersionUID = -8436289855400551515L;
15     /** 姓名 **/
16     private String name;
17 
18     /** 电子邮件 **/
19     private Email email;
20 
21     public Person() {
22     }
23 
24     public Person(String name, Email email) {
25         this.name = name;
26         this.email = email;
27     }
28 
29     public Person(String name) {
30         this.name = name;
31     }
32 
33 
34 
35     public String getName() {
36         return name;
37     }
38 
39     public void setName(String name) {
40         this.name = name;
41     }
42 
43     public Email getEmail() {
44         return email;
45     }
46 
47     public void setEmail(Email email) {
48         this.email = email;
49     }
50     
51 }

 

 1 package com.itinfo.IOcopy;
 2 
 3 import java.io.Serializable;
 4 
 5 /**
 6  * @author Wáng Chéng Dá
 7  * @create 2017-02-24 9:14
 8  */
 9 public class Email implements Serializable {
10 
11     private static final long serialVersionUID = 1820313496253067610L;
12     private String type;
13     private String content;
14 
15     public Email(String content) {
16         this.content = content;
17     }
18 
19     public Email(String type, String content) {
20         this.type = type;
21         this.content = content;
22     }
23 
24     public Email() {
25     }
26 
27     public String getType() {
28         return type;
29     }
30 
31     public void setType(String type) {
32         this.type = type;
33     }
34 
35     public String getContent() {
36         return content;
37     }
38 
39     public void setContent(String content) {
40         this.content = content;
41     }
42 
43     @Override
44     public String toString() {
45         return "Email{" +
46                 "type='" + type + '\'' +
47                 ", content='" + content + '\'' +
48                 '}';
49     }
50 
51 }
 1 package com.itinfo.IOcopy;
 2 
 3 /**
 4  * 深拷贝测试
 5  *
 6  * @author Wáng Chéng Dá
 7  * @create 2017-02-24 9:12
 8  */
 9 public class Client {
10     public static void main(String[] args) {
11         //写封邮件
12         Email email = new Email("请参加会议", "请与今天12:30到二会议室参加会议...");
13 
14         Person person1 = new Person("张三", email);
15 
16         Person person2 = CloneUtils.clone(person1);
17         person2.setName("李四");
18         Person person3 = CloneUtils.clone(person1);
19         person3.setName("王五");
20         
21         System.out.println(person1.getName() + "的邮件内容是:" + person1.getEmail().getContent());
22         System.out.println(person2.getName() + "的邮件内容是:" + person2.getEmail().getContent());
23         System.out.println(person3.getName() + "的邮件内容是:" + person3.getEmail().getContent());
24 
25         person1.getEmail().setContent("请与今天12:00到二会议室参加会议...");
26 
27         System.out.println("------------修改张三的邮件内容-------------");
28 
29         System.out.println(person1.getName() + "的邮件内容是:" + person1.getEmail().getContent());
30         System.out.println(person2.getName() + "的邮件内容是:" + person2.getEmail().getContent());
31         System.out.println(person3.getName() + "的邮件内容是:" + person3.getEmail().getContent());
32     }
33 }

 

控制台输出:

张三的邮件内容是:请与今天12:30到二会议室参加会议...
李四的邮件内容是:请与今天12:30到二会议室参加会议...
王五的邮件内容是:请与今天12:30到二会议室参加会议...
------------修改张三的邮件内容-------------
张三的邮件内容是:请与今天12:00到二会议室参加会议...
李四的邮件内容是:请与今天12:30到二会议室参加会议...
王五的邮件内容是:请与今天12:30到二会议室参加会议...

posted @ 2017-02-24 15:59  Chinda  阅读(628)  评论(0编辑  收藏  举报