浅克隆与深克隆在Java中的应用及区别
核心概念
- 浅克隆
复制对象时仅克隆基本数据类型字段,引用类型字段共享原对象引用。实现方式:
class Person implements Cloneable {
String name;
Address address; // 引用类型字段
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // 默认浅克隆
}
}
class Address {
String city;
}
2.深克隆
完全独立复制对象及其关联对象:
class DeepPerson implements Cloneable {
String name;
Address address;
@Override
protected Object clone() throws CloneNotSupportedException {
DeepPerson cloned = (DeepPerson) super.clone();
cloned.address = new Address(); // 新建独立地址对象
cloned.address.city = this.address.city;
return cloned;
}
}
应用场景对比
特性 | 浅克隆 | 深克隆 |
---|---|---|
内存消耗 | 低(共享引用) | 高(创建新对象) |
数据隔离性 | 弱(修改影响原对象) | 强(完全隔离) |
实现复杂度 | 简单(自动实现) | 复杂(需递归处理) |
适用场景 | 不可变对象/简单结构 | 复杂对象层级/需要隔离修改 |
深度克隆进阶实现
- 序列化方案(需实现Serializable接口)
import java.io.*;
class SerialCloneable implements Serializable {
public Object deepClone() throws IOException, ClassNotFoundException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(this);
try (ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis)) {
return ois.readObject();
}
}
}
}
2.嵌套对象克隆测试
public static void main(String[] args) throws Exception {
// 浅克隆测试
Address addr = new Address("Beijing");
Person original = new Person("Alice", addr);
Person cloned = (Person) original.clone();
cloned.address.city = "Shanghai";
System.out.println(original.address.city); // 输出"Shanghai"
// 深克隆测试
DeepPerson deepOriginal = new DeepPerson("Bob", new Address("Guangzhou"));
DeepPerson deepClone = (DeepPerson) deepOriginal.clone();
deepClone.address.city = "Shenzhen";
System.out.println(deepOriginal.address.city); // 保持"Guangzhou"
}
核心差异总结
-
对象关系拓扑:
- 浅克隆:生成对象图与原对象共享叶节点
- 深克隆:构建完全独立的对象树
-
内存模型表现:
3.修改传播特性:
最佳实践建议
- 优先考虑不可变对象设计
- 复杂对象推荐使用深克隆框架(如Apache Commons Lang3的SerializationUtils)
- 对于循环引用结构,需实现引用追踪机制
- 注意克隆过程中静态字段的处理