Java中实现深拷贝需手动重写clone()方法,对每个可变引用字段调用其clone()或构造新实例;要求所有引用类型实现Cloneable并正确重写clone(),集合等标准类需遍历克隆元素,不可变类可直接赋值,异常需处理,泛型擦除需注意类型安全。

在 Java 中,直接重写 clone() 方法默认只做浅拷贝,对引用类型成员只是复制引用地址,而非创建新对象。要实现深层拷贝(即对所有嵌套的引用类型也创建独立副本),需手动在 clone() 中对每个复杂引用字段调用其自身的 clone() 或构造新实例。
确保被引用类型支持克隆
深层拷贝的前提是:所有需要深拷贝的引用类型(如自定义类、集合、日期等)本身必须正确实现 Cloneable 接口并重写 clone() 方法,且该方法返回的是其自身类型的独立副本。
- 若使用
ArrayList、HashMap等标准集合,它们不重写clone()(仅继承Object.clone(),仍是浅拷贝),需手动遍历并克隆每个元素 - 自定义类(如
Address、UserProfile)必须声明implements Cloneable,并在clone()中调用super.clone()后,对内部引用字段逐个深拷贝 - 不可变类(如
String、LocalDateTime)无需深拷贝,直接赋值即可
在 clone() 中手动处理每个引用字段
重写 clone() 时,不能只依赖 super.clone(),而应在返回前对每个可变引用字段单独克隆:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 对数组:用
Arrays.copyOf()或循环克隆每个元素 - 对集合:新建同类型集合,遍历原集合,对每个元素调用
clone()(要求元素类型可克隆)或通过构造器重建 - 对自定义对象:显式调用其
clone()方法,并捕获CloneNotSupportedException - 示例:
this.address = (Address) original.address.clone();
注意 clone() 的异常与泛型擦除问题
Object.clone() 声明抛出 CloneNotSupportedException,因此重写方法必须声明该异常或用 try-catch 包裹。此外,泛型信息在运行时被擦除,无法自动推断元素类型,所以集合深拷贝必须明确知道元素是否支持克隆。
立即学习“Java免费学习笔记(深入)”;
- 建议将
clone()方法声明为public并返回具体类型(如Person clone()),提升可读性与类型安全 - 避免在不可克隆的字段上强行调用
clone(),否则运行时报CloneNotSupportedException - 若某字段无法克隆(如第三方类未实现
Cloneable),可考虑用序列化/反序列化替代,或改用构造器传参方式重建
替代方案:序列化实现通用深拷贝
当对象结构复杂、引用类型多且难以统一维护 clone() 逻辑时,可通过序列化实现通用深拷贝(要求所有字段类型都可序列化):
- 将对象写入
ByteArrayOutputStream+ObjectOutputStream - 再从
ByteArrayInputStream+ObjectInputStream读回新对象 - 优点:无需每层手动克隆;缺点:性能较低、要求
Serializable、不支持 transient 字段、反射开销大 - 仅建议用于原型开发或低频场景,生产环境优先完善
clone()链路

















