java对象拷贝分三类:引用拷贝仅复制地址、不创建新对象;浅拷贝创建新对象但共享引用字段;深拷贝则完全独立,递归复制所有嵌套对象。

Java 里没有真正的引用传递,只有值传递——基本类型传值的副本,引用类型传的是对象地址的副本。所谓“对象拷贝”,本质是在这个传递机制基础上,人为构造独立副本的行为,核心在于控制新对象与原对象在内存中是否共享引用字段。
引用拷贝:只是多了一个指针
这是最轻量、也最容易误用的操作。比如 User u1 = new User(); User u2 = u1;,u2 并没创建新对象,只是复制了 u1 指向堆中对象的地址。两个变量操作的是同一块内存。
- 修改 u2.name,u1.name 也会变
- 适合只读场景或明确需要共享状态的逻辑
- 开发中应避免在多层方法调用中反复赋值引用,否则容易引发隐蔽的数据污染
浅拷贝:新对象 + 共享引用字段
通过实现 Cloneable 并重写 clone() 得到一个新对象实例,但所有引用类型字段(如 List、Date、自定义对象等)仍指向原对象中的同一份数据。
- 基本类型字段(int、boolean 等)被真正复制
- 引用字段只是地址复制,不是内容复制
- 适用于对象结构扁平、引用字段不常修改,或修改后本就期望影响原对象的场景
深拷贝:彻底隔离,互不影响
新对象及其所有嵌套引用对象都重新创建,内存完全独立。常见实现方式有:
- 手动逐层 new + 赋值(可控但繁琐)
- 利用序列化(如
ObjectOutputStream写入字节数组再反序列化),要求所有嵌套类都实现Serializable - 使用 JSON 工具(如 Jackson/Gson)先转字符串再反解析,注意类型丢失和 transient 字段问题
- 借助 Lombok 的
@Builder(toBuilder = true)或 Apache Commons Lang 的SerializationUtils.clone()
选哪种拷贝,关键看业务语义
不是越深越好,也不是越浅越省事。判断依据是:修改副本时,是否允许原对象状态随之改变?
- 如果只是临时计算、导出、缓存快照——深拷贝更安全
- 如果对象含大量不可变字段(如 final String、LocalDateTime),且引用字段极少或只读——浅拷贝足够
- 如果对象本身设计为可变且需协同更新(如共享配置上下文)——引用拷贝反而符合意图
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











