你好,我是风一样的树懒,一个工作十多年的后端专家,曾就职京东、阿里等多家互联网头部企业。公众号“吴计可师”,已经更新了近百篇高质量的面试相关文章,喜欢的朋友欢迎关注点赞
深克隆与浅克隆的理解及应用实例
一、概念解析
-
浅克隆(Shallow Clone)
- 定义:复制对象的基本类型字段值,对引用类型字段仅复制其内存地址,新旧对象共享同一引用对象。
- 特点:速度快,但引用类型字段的修改会互相影响。
-
深克隆(Deep Clone)
- 定义:递归复制对象及其所有引用对象,生成完全独立的副本。
- 特点:数据隔离性好,但实现复杂且性能开销较大。
二、实现方式对比
| 克隆类型 | 实现方法 | 适用场景 |
|---|---|---|
| 浅克隆 | 默认clone()方法(需实现Cloneable接口) | 引用对象无需独立修改 |
| 深克隆 | 递归调用clone()或序列化/反序列化 | 需完全隔离引用对象的复杂结构 |
三、代码示例
-
浅克隆实现
class Address implements Cloneable { private String city; public Address(String city) { this.city = city; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } class Person implements Cloneable { private String name; private Address address; public Person(String name, Address address) { this.name = name; this.address = address; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); // 仅复制address引用 } } // 使用示例 Address addr = new Address("北京"); Person p1 = new Person("张三", addr); Person p2 = (Person) p1.clone(); p2.getAddress().setCity("上海"); // p1的address也会变为"上海" -
深克隆实现(递归clone)
class Person implements Cloneable { // ... 同上 ... @Override protected Object clone() throws CloneNotSupportedException { Person cloned = (Person) super.clone(); cloned.address = (Address) address.clone(); // 复制address对象 return cloned; } } // 使用示例 Person p2 = (Person) p1.clone(); p2.getAddress().setCity("上海"); // p1的address仍为"北京" -
深克隆实现(序列化)
import java.io.*; public class DeepCloneUtil { public static <T extends Serializable> T deepClone(T obj) { try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(obj); ObjectInputStream ois = new ObjectInputStream( new ByteArrayInputStream(bos.toByteArray())); return (T) ois.readObject(); } catch (Exception e) { throw new RuntimeException("深克隆失败", e); } } } // 使用示例 Person p2 = DeepCloneUtil.deepClone(p1); p2.getAddress().setCity("上海"); // p1不受影响
四、应用场景实例
-
游戏存档与恢复(深克隆)
- 需求:玩家存档需完全独立,恢复时不影响当前游戏状态。
- 实现:深克隆游戏角色对象,确保属性、装备等引用数据独立存储。
-
多线程共享配置(浅克隆)
- 需求:多个线程读取同一配置模板,且模板本身不变。
- 实现:浅克隆配置对象,共享不变的引用数据,节省内存。
-
订单快照生成(深克隆)
- 需求:订单支付前生成独立快照,避免后续修改影响快照数据。
- 实现:深克隆订单对象,确保商品、价格等信息完全独立。
五、注意事项
- 性能考量:深克隆递归复制或序列化可能影响性能,尤其在对象层级深时。
- 循环引用处理:深克隆需避免对象间循环引用导致的栈溢出,可通过缓存已克隆对象解决。
- 序列化限制:使用序列化方式时,所有涉及类必须实现
Serializable接口,且transient字段不会被复制。
六、总结
- 浅克隆适用于引用对象无需修改或共享资源场景,实现简单高效。
- 深克隆确保数据完全隔离,适合需独立副本的复杂结构,但需注意实现复杂度与性能开销。
- 根据业务需求合理选择克隆策略,必要时结合设计模式(如原型模式)优化对象复制流程。
今天文章就分享到这儿,喜欢的朋友可以关注我的公众号,回复“进群”,可进免费技术交流群。博主不定时回复大家的问题。 公众号:吴计可师