Cloneable 接口(標記接口,無方法)。clone() 方法,聲明為 public。super.clone() 獲取淺拷貝基礎。否則拋出 CloneNotSupportedException。
Object.clone() 默認行為:分配新對象,逐位複製字段值。基本類型獨立,引用類型共享同一對象。
class ClassA { int a; void doubleA() { a *= 2; } }
class ClassB implements Cloneable {
int b;
ClassA ca = new ClassA(11);
public Object clone() {
try { return super.clone(); }
catch (CloneNotSupportedException e) { throw new AssertionError(); }
}
}
// 測試
ClassB cb = new ClassB(); cb.b = 222;
ClassB cb2 = (ClassB) cb.clone();
cb2.b = 3333;
cb2.ca.doubleA(); // 修改共享的 ca
System.out.println(cb.ca); // 22 ← 被影響!
System.out.println(cb2.ca); // 22
在 clone() 中對可變引用字段遞歸調用 clone():
class ClassA implements Cloneable { ... public Object clone() { return super.clone(); } }
class ClassB implements Cloneable {
int b;
ClassA ca = new ClassA(11);
public Object clone() {
ClassB cb = (ClassB) super.clone();
cb.ca = (ClassA) ca.clone(); // 關鍵:深拷貝內部對象
return cb;
}
}
// 測試結果:cb.ca 保持 11,cb2.ca 變為 22,互不干擾
String、包裝類、final 類無需深拷貝,共享安全。
方案:複製構造器 new ThirdParty(obj)、序列化反序列化、手工構建新實例複製字段。
需維護 Map 避免無限遞歸,或使用序列化框架(如 Kryo)自動處理。
clone() 時拋出不可檢查異常(如 AssertionError)包裝 CloneNotSupportedException,簡化調用端。Cloneable(Effective Java Item 13 建議)。克隆看似簡單,實則暗藏共享可變狀態的陷阱。明確語義、最小化可變性,才是正道。