object.clone()默认浅拷贝,防止状态污染需在重写clone()中手动深拷贝可变引用(如arraylist、自定义pojo),而string、integer等不可变对象可直接赋值;类须实现cloneable、clone()改为public并调super.clone(),且嵌套可变类型也需支持克隆。

Java 中 Object.clone() 本身只做浅拷贝,无法自动避免引用对象被篡改。要真正隔离修改、防止状态污染,必须在重写的 clone() 方法中**手动切断所有可变引用的共享链**——不是靠“启用某个开关”,而是逐字段判断、有选择地深拷贝。
必须满足的三个前提条件
缺一不可,否则连浅拷贝都会失败:
- 当前类声明
implements Cloneable(仅标记,不提供方法) -
clone()方法改为public,且第一行必须调用super.clone() - 所有需要深拷贝的嵌套引用类型(如
Address、ArrayList)也得各自实现Cloneable并重写public clone()
哪些字段要深拷贝,哪些可以直接用
关键在区分「可变」与「不可变」:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
-
不用处理(直接赋值即可):基本类型(
int、boolean)、不可变类(String、LocalDateTime、Integer、BigDecimal)——它们的“修改”本质是新建对象,原引用不受影响 -
必须深拷贝:自定义 POJO(如
Address)、集合(ArrayList、HashMap)、数组(尤其是对象数组)、Date、StringBuilder等——这些对象内部状态可被外部 setter 或方法改变,共享即风险
典型字段的深拷贝写法
以一个含 Address 和 List<string></string> 的 Person 类为例:
-
address字段:if (this.address != null) cloned.address = this.address.clone();(前提是Address类已正确实现clone()) -
hobbies(List<string></string>):cloned.hobbies = new ArrayList(this.hobbies);(元素是String,不可变,构造新集合即可) -
orders(List<order></order>,Order可变):cloned.orders = this.orders.stream().map(Order::clone).collect(Collectors.toList()); -
photos(Photo[]数组):cloned.photos = Arrays.stream(this.photos).map(Photo::clone).toArray(Photo[]::new);(不能只写this.photos.clone(),那是浅的)
绕不开的坑和更稳的选择
手动克隆容易踩到硬伤:
-
循环引用(A→B→A):递归调
clone()会栈溢出,需用IdentityHashMap<object object></object>缓存已克隆对象 -
final 字段:
super.clone()后无法重新赋值,编译报错;此时clone()机制失效,必须换方案 -
第三方类未实现 Cloneable(如
java.time.ZonedDateTime):不能调.clone(),只能用构造器重建或序列化 -
推荐替代方案:拷贝构造器(
public Person(Person src))或静态工厂(Person.copyOf(src))——逻辑清晰、支持final、不绕过构造逻辑、类型安全
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










