Java深拷貝與淺拷貝的概念
淺拷貝(Shallow Copy)只復制對象的引用,而不復制對象本身。拷貝后的對象和原對象共享同一塊內存地址中的子對象。修改其中一個對象的非基本類型屬性時,另一個對象的對應屬性也會被修改。
深拷貝(Deep Copy)會復制對象及其所有子對象,生成一個完全獨立的新對象。拷貝后的對象和原對象完全分離,修改其中一個對象的屬性不會影響另一個對象。
內存分析示例
假設有一個Person
類,包含name
(String
)和address
(Address
類)屬性:
class Address {String city;// 構造方法、getter/setter省略
}class Person implements Cloneable {String name;Address address;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone(); // 默認淺拷貝}
}
淺拷貝實現與內存表現
Person p1 = new Person();
p1.name = "Alice";
p1.address = new Address("Beijing");Person p2 = (Person)p1.clone();
內存表現:
p1
和p2
是兩個獨立對象,但它們的address
屬性指向同一個Address
對象- 修改
p2.address.city
會影響p1.address.city
深拷貝實現方式
方法1:重寫clone()
@Override
protected Object clone() throws CloneNotSupportedException {Person cloned = (Person)super.clone();cloned.address = (Address)this.address.clone(); // 遞歸克隆引用對象return cloned;
}
方法2:序列化實現
public Person deepCopy() throws IOException, ClassNotFoundException {ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(this);ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return (Person)ois.readObject();
}
內存表現:
p1
和p2
完全獨立,包括所有引用類型屬性- 修改
p2.address.city
不會影響p1.address.city
性能與適用場景
淺拷貝:
- 性能更好,僅復制引用
- 適合引用對象不可變或不需要獨立修改的場景
深拷貝:
- 性能開銷較大,需要遞歸復制所有對象
- 適合需要完全獨立對象的場景,如多線程環境
注意事項
String
等不可變對象在淺拷貝中是安全的- 數組的
clone()
方法是淺拷貝 - 深拷貝可能導致循環引用問題
- 使用第三方庫(如Apache Commons Lang的
SerializationUtils
)可以簡化深拷貝實現