如何利用序列化來完成對象的拷貝呢?在內存中通過字節流的拷貝是比較容易實現的。把母對象寫入到一個字節流中,再從字節流中將其讀出來,這樣就可以創建一個新的對象了,並且該新對象與母對象之間並不存在引用共享的問題,真正實現對象的深拷貝。
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; } }
使用該工具類的對象必須要實現Serializable接口,否則是沒有辦法實現克隆的。
public class Person implements Serializable{ private static final long serialVersionUID = 2631590509760908280L; .................. //去除clone()方法 } public class Email implements Serializable{ private static final long serialVersionUID = 1267293988171991494L; .................... }
所以使用該工具類的對象只要實現Serializable接口就可實現對象的克隆,無須繼承Cloneable接口實現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到二會議室參加會議...