java中clone()默认执行浅拷贝,仅复制基本类型值和引用地址,导致新旧对象共享可变引用类型实例;需重写clone()手动深拷贝或采用拷贝构造器、序列化等替代方案。

Java 中 clone() 方法对对象内部的关联引用默认不做复制,仅复制引用本身——也就是“地址拷贝”,新旧对象共享同一堆内存中的被引用对象。
浅拷贝是 clone 的默认行为
Object 类提供的 clone() 是 native 实现,它执行的是逐字段(field-by-field)拷贝:
- 基本类型字段(如 int、boolean)直接复制值;
- 引用类型字段(如 ArrayList、自定义对象、数组)只复制引用地址,不创建新对象;
- String 等不可变类虽是引用类型,但因不可修改,表现上像值拷贝,实际仍是地址共享。
关联引用共享会带来副作用
当原对象内部包含可变引用类型(比如 ArrayList、HashMap、可变 POJO)时,克隆后两者指向同一个实例:
- 修改克隆对象的
list.add(x),原对象的 list 也会变化; - 更新克隆对象中
address.setCity("Shanghai"),原对象的 address 同样被改; - 这种共享在多线程或状态隔离场景下极易引发数据污染或并发异常。
要切断关联引用,必须主动深拷贝
默认 clone() 不会递归处理嵌套对象。若需完全独立副本,需在重写的 clone() 方法中显式处理:
- 对每个可变引用字段调用其自身的
clone()(前提是该类也支持克隆); - 对集合类(如 ArrayList),需遍历元素并克隆每个可变元素,不能只调用
list.clone()(那仍是浅的); - 不可变对象(String、Integer 等)无需额外操作,直接赋值即可。
替代方案更可控
相比手动维护 clone(),以下方式对关联引用的控制更清晰:
- 拷贝构造器:显式 new 每个嵌套对象,逻辑透明,类型安全;
- 序列化反序列化:借助 ObjectOutputStream/ObjectInputStream 实现自动深拷贝,要求所有层级类实现
Serializable; - 第三方工具:如 Apache Commons Lang 的
SerializationUtils.clone(),封装了序列化细节。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











