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

Java 中 clone() 方法默认不处理复杂关联关系,它只做浅拷贝——对引用字段仅复制地址,不复制所指向的对象。要正确拷贝复杂关联(比如嵌套对象、集合、树形结构等),必须手动干预,逐层确保每个可变引用都生成独立副本。
必须让所有关联类型支持克隆
深拷贝的前提是:每个被引用的类都实现了 Cloneable 接口,并重写了 clone() 方法,且该方法返回的是自身的新实例。例如:
-
Address类需声明implements Cloneable,并在clone()中调用super.clone() -
List<User>这类标准集合本身不深拷贝元素,即使你调用list.clone(),得到的仍是原 list 的浅拷贝,内部元素引用未变 - 第三方类若未实现
Cloneable(如某些 SDK 中的工具类),不能直接调用.clone(),否则运行时报CloneNotSupportedException
在 clone() 中显式克隆每个关联字段
重写 clone() 时,不能只依赖 super.clone()。需对每个可变引用字段单独处理:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 对单个自定义对象:如
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,否则可能在运行时崩溃。
立即学习“Java免费学习笔记(深入)”;
复杂场景下建议换用序列化
当关联层级深、类型杂(含第三方类、流、资源句柄等)、或维护成本过高时,clone() 容易出错。此时更稳妥的做法是使用序列化/反序列化:
- 要求所有关联类实现
Serializable - 通过
ObjectOutputStream写入字节流,再用ObjectInputStream读出新对象 - 它天然递归处理整个对象图,无需手动逐字段判断和克隆
- 缺点是性能较低、不能序列化 transient 字段或非 Serializable 成员

















