呼叫 Object.clone() 時實際發生什麼?覆寫 clone() 時,super.clone() 關鍵在何處?
根類別 clone() 負責:
它不只是預留空間複製參考,而是調查欲複製物件的確切大小,然後逐位複製。因根類別不知衍生類細節,此過程需用 RTTI 判斷實際類型與大小,才能建立正確空間並正確位元複製。
//: Snake.java
public class Snake implements Cloneable {
private Snake next;
private char c;
Snake(int i, char x) {
c = x;
if(--i > 0) next = new Snake(i, (char)(x + 1));
}
void increment() { c++; if(next != null) next.increment(); }
public String toString() {
String s = ":" + c;
if(next != null) s += next.toString();
return s;
}
public Object clone() {
Object o = null;
try { o = super.clone(); }
catch (CloneNotSupportedException e) {}
return o;
}
public static void main(String[] args) {
Snake s = new Snake(5, 'a');
System.out.println("s = " + s);
Snake s2 = (Snake)s.clone();
System.out.println("s2 = " + s2);
s.increment();
System.out.println("after s.increment, s2 = " + s2);
}
} ///:~
Snake 形成鏈結串列,每節皆為 Snake 物件。輸出:
s = :a:b:c:d:e s2 = :a:b:c:d:e after s.increment, s2 = :a:c:d:e:f
只有第一節被 Object.clone() 複製——這是 淺層複製。s.increment() 修改鏈結時,s2 共享的後續節點也跟著變。
通常在可複製類別中呼叫 super.clone() 確保基類行為(含 Object.clone())執行。隨後必須對物件內每個參考顯式呼叫 clone(),否則參考會別名指向原物件。建構子鏈自動從基類向下執行,但 clone() 非建構子,無自動機制,必須手動逐層處理。