Java 無指針概念,但對象傳遞實為引用傳遞。簡單賦值 (`obj2 = obj1`) 僅複製引用,修改會影響原對象。若需獨立副本,必須正確實現拷貝機制。
public void changeObj(Obj o) { o.str = "changed"; } // 修改原對象
public void changePri(int i) { i = 22; } // 不影響原變量
基本類型傳值,對象傳引用。這是理解拷貝必要性的前提。
Cloneable 標記接口(否則拋 CloneNotSupportedException)。clone() 並調用 super.clone()(native 方法,高效逐位複製)。public 訪問權限。
class CloneB implements Cloneable {
int aInt;
UnCloneA unCA; // 引用類型
// 僅調用 super.clone()
}
結果:基本類型獨立,引用類型指向同一對象。修改 `b2.unCA` 會影響 `b1.unCA`。
class CloneB implements Cloneable {
int aInt;
UnCloneA unCA;
@Override
public Object clone() {
CloneB o = (CloneB) super.clone();
o.unCA = (UnCloneA) unCA.clone(); // 關鍵:手動拷貝引用字段
return o;
}
}
要求所有引用類型字段均實現 Cloneable 並重寫 clone()。
| 類型 | 拷貝策略 |
|---|---|
| String | 不可變對象,淺拷貝即安全(修改實為新建對象)。 |
| StringBuffer / final 類 / 第三方庫類 | 無法繼承實現 clone(),需在 clone() 中手動 new StringBuffer(old.toString()) 重建。 |
| 集合 | 需逐元素深拷貝,或使用序列化/JSON 轉換實現通用深拷貝。 |
ByteArrayOutputStream + ObjectOutputStream 寫入,再反序列化。通用但需實現 Serializable,性能一般。Gson/Jackson 序列化為 JSON 再反序列化。跨平台、可讀、性能尚可,首選方案。避免手寫 clone() 的無限遞歸與維護地獄,拥抱序列化或映射框架,是現代 Java 開發的明智之選。