java中object.clone()默认仅实现浅拷贝,深拷贝需手动处理:类必须实现cloneable接口、重写public clone()方法并调用super.clone(),再对每个可变引用字段递归clone或新建副本,确保对象图完全独立。

Java 中 Object.clone() 默认只支持浅拷贝,要实现深拷贝,必须手动改造:让每个引用类型字段也调用 clone() 或重新创建独立副本,并确保整个对象图中所有可变对象都被复制。
确保类实现 Cloneable 接口并重写 clone 方法
这是基础前提。仅声明 Cloneable 不够,还需重写 clone() 并去掉 protected 修饰符(通常改为 public),否则外部无法调用;同时需捕获 CloneNotSupportedException(虽然 Cloneable 是标记接口,但 Object.clone() 仍会检查它)。
- 不实现
Cloneable直接调用clone()会抛出CloneNotSupportedException -
super.clone()返回的是浅拷贝结果,后续需在此基础上对引用字段逐个深拷贝 - 避免直接返回
super.clone(),除非所有字段都是基本类型或不可变对象(如String、Integer)
对每个可变引用字段单独克隆
深拷贝的关键在于:对类中每个非基本、非不可变的引用字段(如自定义对象、ArrayList、Date 等),不能直接赋值原对象引用,而应调用其 clone() 方法或用构造器/工厂方法新建等价对象。
- 如果字段是自定义类,该类也必须支持克隆(实现
Cloneable+ 重写clone()) - 集合类如
ArrayList:先super.clone()得到新集合容器,再遍历原集合,对每个元素调用clone()并 add 到新集合 - 数组字段:若为对象数组,需新建数组并逐个克隆元素;基本类型数组可直接用
Arrays.copyOf() - 注意避免循环引用——若对象图存在环,需引入缓存机制记录已克隆对象,防止无限递归
处理不可变与可变类型的区分
不是所有字段都需要克隆。识别字段是否可变,能减少冗余操作并提升性能:
-
String、LocalDateTime、BigInteger等不可变类型,直接赋值即可,无需克隆 -
Date、Calendar、StringBuilder、自定义 POJO 等可变类型,必须深拷贝 - 第三方库对象(如 Jackson 的
JsonNode)需查阅文档确认是否可变;不确定时按可变处理更安全
替代方案:序列化或第三方库更可靠
手写克隆逻辑易出错(尤其嵌套深、类型多时)。生产环境推荐更健壮的方式:
- 使用序列化(如
ObjectOutputStream+ByteArrayInputStream):要求所有字段可序列化,且无transient敏感数据 - 用 Apache Commons Lang 的
SerializationUtils.clone()封装了序列化细节 - 用 Gson / Jackson 先转 JSON 再反序列化,适合 DTO 场景,但需注意类型擦除和泛型问题
- Lombok 的
@Data不生成深克隆;可用@Builder配合手动构建,或结合@Singular控制集合初始化
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











