若需修改一個對象,同時不想改變調用者的對象,就要制作該對象的一個本地副本。這也是本地副本最常見的一種用途。若決定制作一個本地副本,只需簡單地使用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庫中專門保留了這樣的一個關鍵字。