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