使用序列化实现对象的拷贝(转载)
文章出处: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到二会议室参加会议... |
深拷贝:
把Person中的 person.setEmail(new Email(person.getEmail().getType(),person.getEmail().getContent())); 注释放开。
控制台输出:
张三的邮件内容是:请与今天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到二会议室参加会议... |