Object.clone() 是 Java 中創建對象副本的核心機制,但其行為細節(淺拷貝)、拋出的異常、Cloneable 接口的標記作用,常讓開發者踩坑。本文從源碼層面剖析,並通過完整代碼示例演示淺/深拷貝的正確實現姿勢。
protected native Object clone() throws CloneNotSupportedException;
public,以便外部調用。Cloneable 標記接口,否則調用直接拋出異常。注意:Cloneable 內部無任何方法,僅作運行時標記。Java 中對象變量存儲的是引用(內存地址)。直接賦值 Person p2 = p1; 只是複製引用,兩個變量指向同一堆內存對象,修改任一變量可見的屬性都會影響另一個。

使用 clone() 可在堆內存中分配新空間,複製字段值,實現真正的對象獨立:

@Override
public ShallowClone clone() {
try {
return (ShallowClone) super.clone(); // 僅調用 Object.clone()
} catch (CloneNotSupportedException e) {
throw new AssertionError(); // 不會發生,因實現了 Cloneable
}
}
運行結果證明:c1.person == c2.person(同一引用地址)。修改 c2.person.name 會影響 c1.person。
@Override
public DeepClone clone() {
try {
DeepClone c = (DeepClone) super.clone();
c.person = person.clone(); // 關鍵:手動複製引用字段
return c;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
運行結果:c1.person != c2.person,內存地址不同,修改互不影響。
new Person(person)),避開 Cloneable 的繁瑣協議。clone() 時:實現 Cloneable、覆寫為 public、深拷貝所有可變引用字段、文檔說明拷貝策略。new ArrayList<>(list) 或流式 list.stream().map(Item::clone).collect(toList())。String、包裝類、LocalDate)無需深拷貝,直接共享引用安全。clone() 機制強大但易誤用。理解「淺拷貝只複製引用,深拷貝遞歸複製對象圖」是核心。現代開發中,拷貝構造函數/建造者模式/序列化反序列化 往往是更清晰、類型安全的替代方案。