若需修改一個對象,同時不想改變調用者的對象,就要製作該對象的一個本機複本。這也是本機複本最常見的一種用途。若決定製作一個本機複本,只需簡單地使用clone()方法即可。Clone是“複製”的意思,即製作完全一模一樣的副本。這個方法在基礎類Object中定義成“protected”(受保護)模式。但在希望複製的任何衍生類中,必須將其覆蓋為“public”模式。例如,標準庫類Vector覆蓋了clone(),所以能為Vector調用clone(),如下所示:
//: Cloning.java// The clone() operation works for only a few// items in the standard Java library.import java.util.*;class Int { private int i; public Int(int ii) { i = ii; } public void increment() { i++; } public String toString() { return Integer.toString(i); }}public class Cloning { public static void main(String[] args) { Vector v = new Vector(); for(int i = 0; i < 10; i++ ) v.addElement(new Int(i)); System.out.println("v: " + v); Vector v2 = (Vector)v.clone(); // Increment all v2's elements: for(Enumeration e = v2.elements(); e.hasMoreElements(); ) ((Int)e.nextElement()).increment(); // See if it changed v's elements: System.out.println("v: " + v); }} ///:~
clone()方法產生了一個Object,後者必須立即重新造型為正確類型。這個例子指出Vector的clone()方法不能自動嘗試複製Vector內包含的每個對象——由於別名問題,老的Vector和複製的Vector都包含了相同的對象。我們通常把這種情況叫作“簡單複製”或者“淺層複製”,因為它只複製了一個對象的“表面”部分。實際對象除包含這個“表面”以外,還包括控制代碼指向的所有對象,以及那些對象又指向的其他所有對象,由此類推。這便是“對象網”或“對象關係網”的由來。若能複製下所有這張網,便叫作“全面複製”或者“深層複製”。
在輸出中可看到淺層複製的結果,注意對v2採取的行動也會影響到v:
v: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]v: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
一般來說,由於不敢保證Vector裡包含的對象是“可以複製”(注釋②)的,所以最好不要試圖複製那些對象。
②:“可以複製”用英語講是cloneable,請留意Java庫中專門保留了這樣的一個關鍵字。