java clone()默认浅拷贝,深拷贝需手动逐层克隆关联对象、集合及数组,要求所有类实现cloneable并重写clone();第三方类未实现时会抛clonenotsupportedexception;复杂场景建议用序列化替代。

Java 中 clone() 方法默认不处理复杂关联关系,它只做浅拷贝——对引用字段仅复制地址,不复制所指向的对象。要正确拷贝复杂关联(比如嵌套对象、集合、树形结构等),必须手动干预,逐层确保每个可变引用都生成独立副本。
必须让所有关联类型支持克隆
深拷贝的前提是:每个被引用的类都实现了 Cloneable 接口,并重写了 clone() 方法,且该方法返回的是自身的新实例。例如:
-
Address类需声明implements Cloneable,并在clone()中调用super.clone() -
List<user></user>这类标准集合本身不深拷贝元素,即使你调用list.clone(),得到的仍是原 list 的浅拷贝,内部元素引用未变 - 第三方类若未实现
Cloneable(如某些 SDK 中的工具类),不能直接调用.clone(),否则运行时报CloneNotSupportedException
在 clone() 中显式克隆每个关联字段
重写 clone() 时,不能只依赖 super.clone()。需对每个可变引用字段单独处理:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 对单个自定义对象:如
this.profile = (UserProfile) original.profile.clone(); - 对集合:新建空集合,遍历原集合,对每个元素调用
clone()或用构造器重建,例如:this.tags = new ArrayList();<br>for (Tag tag : original.tags) { this.tags.add(tag.clone()); } - 对数组:用
Arrays.copyOf()或手动遍历克隆每个元素(若元素可克隆) - 不可变类型(
String、LocalDateTime、Integer等)可直接赋值,无需克隆
注意异常和泛型擦除带来的限制
Object.clone() 声明抛出 CloneNotSupportedException,因此你的 clone() 方法必须声明该异常,或用 try-catch 包裹。同时,泛型在运行时已擦除,无法自动识别集合中元素的实际类型是否支持克隆——这意味着你必须在代码中明确知道 tags 里的每个 Tag 都实现了 Cloneable,否则可能在运行时崩溃。
复杂场景下建议换用序列化
当关联层级深、类型杂(含第三方类、流、资源句柄等)、或维护成本过高时,clone() 容易出错。此时更稳妥的做法是使用序列化/反序列化:
- 要求所有关联类实现
Serializable - 通过
ObjectOutputStream写入字节流,再用ObjectInputStream读出新对象 - 它天然递归处理整个对象图,无需手动逐字段判断和克隆
- 缺点是性能较低、不能序列化 transient 字段或非 Serializable 成员
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










