淺拷貝和深拷貝是兩種不同的對象復制方式,主要區別在于它們如何處理對象內部的引用類型字段。
淺拷貝 (Shallow Copy)
特點:
只復制對象本身(基本類型字段)和對象中的引用(地址)
不復制引用指向的實際對象
原始對象和拷貝對象共享內部引用對象
示例:
class Person {String name;Address address; // 引用類型// 淺拷貝方法public Person shallowCopy() {Person copy = new Person();copy.name = this.name; // 基本類型或String的復制copy.address = this.address; // 只是復制引用return copy;}
}
結果:
修改拷貝對象的
address
會影響原始對象,因為它們引用同一個Address對象
深拷貝 (Deep Copy)
特點:
復制對象本身及其所有引用的對象
遞歸復制所有引用對象直到基本類型
原始對象和拷貝對象完全獨立,不共享任何引用
示例:
class Person {String name;Address address;// 深拷貝方法public Person deepCopy() {Person copy = new Person();copy.name = this.name;copy.address = new Address(this.address.street, this.address.city); // 創建新對象return copy;}
}
結果:
修改拷貝對象的
address
不會影響原始對象,因為它們引用不同的Address對象
對比表格
特性 | 淺拷貝 | 深拷貝 |
---|---|---|
復制內容 | 對象本身和引用地址 | 對象本身和所有引用對象 |
內存消耗 | 較少 | 較多 |
性能 | 較快 | 較慢 |
獨立性 | 不獨立(共享引用對象) | 完全獨立 |
實現復雜度 | 簡單 | 復雜(需要遞歸復制所有引用對象) |
實際應用場景
使用淺拷貝:
當對象內部引用是不可變的(如String)
當明確需要共享某些引用對象時
性能要求高且不需要完全獨立的對象時
使用深拷貝:
需要完全獨立的對象副本時
當對象包含可變引用對象且不希望共享時
在多線程環境中需要安全地共享數據時
Java中的實現方式
淺拷貝:
實現
Cloneable
接口并重寫clone()
方法手動復制字段
深拷貝:
遞歸實現
clone()
方法使用序列化和反序列化
使用第三方庫如Apache Commons Lang的
SerializationUtils.clone()
使用復制構造函數或工廠方法
// 使用序列化實現深拷貝
public static <T extends Serializable> T deepCopy(T object) {try {ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(baos);oos.writeObject(object);ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bais);return (T) ois.readObject();} catch (Exception e) {throw new RuntimeException(e);}
}