Java中clone()默认为浅拷贝,深拷贝需手动处理引用字段;浅拷贝仅复制引用地址,深拷贝需逐层克隆对象;推荐用构造方法、record、JSON序列化等更安全方式替代clone()。

Java 中的 clone() 方法默认只支持浅拷贝,要实现深拷贝必须手动处理引用类型字段——这是核心区别,也是最容易出错的地方。
浅拷贝:只复制对象本身,不复制引用指向的内容
调用 Object.clone() 时,JVM 会创建一个新对象,并把原对象的字段值逐个复制过去。对基本类型(如 int、boolean)没问题;但对引用类型(如 String、ArrayList、自定义对象),只是复制了引用地址,新旧对象仍指向同一块堆内存。
- 必须让类实现
Cloneable接口,否则抛CloneNotSupportedException - 重写
clone()方法并设为public(因为父类中是protected) - 直接调用
super.clone()即可完成浅拷贝
深拷贝:所有层级的对象都独立复制
深拷贝要求对象及其内部所有引用类型的字段(包括嵌套对象)都生成全新副本。仅靠 super.clone() 不够,需对每个引用字段单独克隆。
- 若字段是可变引用类型(如
ArrayList),需调用其clone()或构造新集合并逐个添加克隆项 - 若字段是自定义对象,该对象也得实现
Cloneable并提供正确clone()方法 - 注意循环引用或复杂图结构,可能需要借助序列化或第三方库(如 Apache Commons Lang 的
SerializationUtils)
更安全的替代方案:避免 clone 的坑
clone() 机制设计较老,存在语义模糊、异常处理繁琐、继承链中易出错等问题。现代 Java 更推荐以下方式:
立即学习“Java免费学习笔记(深入)”;
- 提供带参构造方法或静态工厂方法,显式复制字段(尤其适合不可变对象)
- 使用记录类(record)+ 自定义复制逻辑,代码简洁且线程安全
- 借助 JSON 序列化(如 Jackson)做深拷贝:先序列化再反序列化,适用于 POJO 且无复杂状态的对象
- 用 Lombok 的
@Builder或@With注解辅助构建副本
关键细节别忽略
即使走 clone() 路线,也要注意几个实际问题:
-
final字段无法在clone()中重新赋值,除非用反射(不推荐)或改用构造器方式 - 如果类有父类,且父类字段也需要深拷贝,子类
clone()中应确保调用父类对应逻辑 -
String、Integer等不可变包装类虽是引用类型,但浅拷贝已足够安全(因不可变)


















