在Java的Object類中定義了(protected)clone()方法,如果自己的類需要clone方法的話需要實現Cloneable介面,並重寫clone()方法和將方法存取層級改為(public)。但是如果自己的類如果屬性比較多,重寫clone方法還是會花去不少時間,更重要的是以後增加或者刪除屬性的時候也要相應修改clone方法,總的來說還是比較麻煩的。
這裡如果對效能不太計較的話,其實可以有一個簡單快速的方法實現clone方法,就是使用Java語言的序列化功能來實現clone方法,如下:
以下是幾個測試的Bean類
import java.io.Serializable; public class A implements Serializable { private static final long serialVersionUID = 1L; private String name; private B b; public String getName() { return name; } public void setName(String name) { this.name = name; } public B getB() { return b; } public void setB(B b) { this.b = b; } @Override public Object clone() { return CloneUtil.clone(this); } } import java.io.Serializable; public class B implements Serializable { private static final long serialVersionUID = 1L; private String name; private C c; public String getName() { return name; } public void setName(String name) { this.name = name; } public C getC() { return c; } public void setC(C c) { this.c = c; } @Override public Object clone() { return CloneUtil.clone(this); } } import java.io.Serializable; public class C implements Serializable, Cloneable { private static final long serialVersionUID = 1L; private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public Object clone() { return CloneUtil.clone(this); } }
Clone工具類,這個類負責通過序列化和還原序列化做到對一個對象的clone
import java.io.*; public class CloneUtil { public static Object clone(Object obj) { Object anotherObj = null; byte[] bytes; ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = null; try { oos = new ObjectOutputStream(baos); oos.writeObject(obj); bytes = baos.toByteArray(); } catch(IOException ex) { throw new RuntimeException(ex.getMessage(), ex); } finally { if (oos != null) { try { oos.close(); } catch (IOException e) { // ignore me } } } ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = null; try { ois = new ObjectInputStream(bais); anotherObj = ois.readObject(); } catch(IOException ex) { throw new RuntimeException(ex.getMessage(), ex); } catch(ClassNotFoundException ex) { throw new RuntimeException(ex.getMessage(), ex); } finally { if (ois != null) { try { ois.close(); } catch (IOException e) { // ignore me } } } return anotherObj; } }
測試類別
public class Test { public static void main(String[] args) throws Exception { A a = new A(); B b = new B(); C c = new C(); c.setName("ccc"); b.setName("bbb"); b.setC(c); a.setName("aaa"); a.setB(b); System.out.println("a: " + a); System.out.println("a: " + a.getName()); System.out.println("a: " + a.getB().getName()); System.out.println("a: " + a.getB().getC().getName()); A anotherA = (A)a.clone(); System.out.println("anotherA: " + anotherA); System.out.println("anotherA: " + anotherA.getName()); System.out.println("anotherA: " + anotherA.getB().getName()); System.out.println("anotherA: " + anotherA.getB().getC().getName()); System.out.println("=== change properties of a ==="); a.setName("aaaaa"); a.getB().setName("bbbbb"); a.getB().getC().setName("ccccc"); System.out.println("a: " + a); System.out.println("a: " + a.getName()); System.out.println("a: " + a.getB().getName()); System.out.println("a: " + a.getB().getC().getName()); System.out.println("anotherA: " + anotherA); System.out.println("anotherA: " + anotherA.getName()); System.out.println("anotherA: " + anotherA.getB().getName()); System.out.println("anotherA: " + anotherA.getB().getC().getName()); System.out.println("=== change properties of anotherA ==="); anotherA.setName("aaaa"); anotherA.getB().setName("bbbb"); anotherA.getB().getC().setName("cccc"); System.out.println("a: " + a); System.out.println("a: " + a.getName()); System.out.println("a: " + a.getB().getName()); System.out.println("a: " + a.getB().getC().getName()); System.out.println("anotherA: " + anotherA); System.out.println("anotherA: " + anotherA.getName()); System.out.println("anotherA: " + anotherA.getB().getName()); System.out.println("anotherA: " + anotherA.getB().getC().getName()); } }
運行測試類別可以看到結果。這裡通過代碼可以看出這種實現還是有一些限制的:
1. 自己的bean必須實現Serializable介面;
2. 由於這種實現使用了序列化,所以效能不是很好,所以如果對象太多,不建議使用;
3. 由於在序列化的過程中沒有將對象序列化到檔案中,而是保留在了記憶體數組中,所以如果對象太大的話,會造成比較大的記憶體使用量,需要注意。