深拷贝和浅拷贝区别¶
一、定义¶
浅拷贝(Shallow Copy)¶
只复制对象本身和基本类型字段,引用类型字段只复制引用,不复制引用指向的对象。
深拷贝(Deep Copy)¶
不仅复制对象本身,还递归复制所有引用类型字段指向的对象。
二、图示¶
原对象 A:
name: "Tom"
address: 对象 B (city="北京")
浅拷贝 A':
name: "Tom"
address: 同一个对象 B ← 引用一样
深拷贝 A':
name: "Tom"
address: 新对象 B' (city="北京") ← 复制一份
三、代码示例¶
class Address {
String city;
}
class Person implements Cloneable {
String name;
Address address;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // 浅拷贝
}
}
浅拷贝¶
Person p1 = new Person("Tom", new Address("北京"));
Person p2 = (Person) p1.clone();
p2.address.city = "上海";
System.out.println(p1.address.city); // 上海!p1 也被改了
深拷贝¶
@Override
protected Object clone() throws CloneNotSupportedException {
Person p = (Person) super.clone();
p.address = new Address(this.address.city); // 复制引用对象
return p;
}
四、实现方式¶
1. 重写 clone()¶
手动 new 每个引用对象。
2. 序列化¶
实现 Serializable,把对象写出去再读回来,天然深拷贝:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(bos.toByteArray()));
return ois.readObject();
3. JSON 序列化¶
简单但要注意循环引用。
五、选择¶
- 对象简单、引用少:浅拷贝。
- 有引用类型且需要独立:深拷贝。
- 用不可变对象:从根本上避免拷贝问题。
clone() 的坑
Cloneable是标记接口,不重写clone()调super.clone()会抛异常。- 数组实现了 Cloneable,但元素引用仍是浅拷贝。
- Effective Java 建议:用拷贝构造器或工厂,不要用 clone()。