Java对象拷贝分浅拷贝和深拷贝:浅拷贝仅复制自身及基本类型字段,引用类型仍共享;深拷贝递归复制整个对象图。选错方式会导致修改副本影响原对象。

Java 中对象拷贝的关键在于:浅拷贝只复制对象自身和基本类型字段,引用类型字段仍共享同一实例;深拷贝则递归复制整个对象图,确保完全独立。选错方式会导致“改副本,原对象也变”的隐蔽 Bug。
浅拷贝的正确实现
适用于字段简单、无深层引用或引用对象本身不可变(如 String、LocalDate)的场景。
- 实现 Cloneable 接口并重写 clone() 方法,调用 super.clone() 即可 —— 这是标准且轻量的方式
- 手动构造新对象(如拷贝构造器或 setter 赋值),对每个字段直接赋值;注意:引用类型变量仍应直接赋值(不 new),否则就变成深拷贝逻辑了
- String 类型虽为引用类型,但因不可变性,在浅拷贝中行为等同于基本类型,无需额外处理
深拷贝的可靠实现方式
当对象含嵌套可变引用(如 Address、List
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
序列化反序列化:最通用方案。要求所有嵌套类都实现 Serializable;用
ObjectOutputStream写入字节数组,再用ObjectInputStream读出新对象。天然递归,不遗漏任何层级 -
手动逐层克隆:在 clone() 中对每个引用字段显式调用其 clone() 或拷贝构造器。例如 Person 中有 Address 字段,则需
this.address = (Address) original.address.clone(); -
第三方工具:Apache Commons Lang 的
SerializationUtils.clone()封装了序列化逻辑;Gson / Jackson 可通过 JSON 序列化+反序列化实现(要求类有无参构造器、字段可访问)
容易踩坑的细节
很多问题不是不会写,而是忽略关键约束:
立即学习“Java免费学习笔记(深入)”;
-
Cloneable 是标记接口:不实现它却调用 clone() 会抛
CloneNotSupportedException - 集合的 clone() 不是深拷贝:ArrayList.clone() 只复制元素引用,内部数组元素仍是原对象 —— 需遍历并 clone 每个元素
- transient 字段不会被序列化深拷贝:若用序列化方式,这些字段在副本中为 null 或默认值
- static 成员不属于对象实例:任何拷贝方式都不会复制 static 字段,它们始终共享
怎么选?看实际需求
没有银弹,只有适配场景:
- 只读或短期临时副本 → 浅拷贝足够,性能好
- 多线程间传递、缓存预热、原型模式创建差异化实例 → 必须深拷贝
- 对象结构稳定、全可序列化 → 优先用序列化深拷贝,代码少、不易漏
- 对性能极度敏感(如高频拷贝小对象)→ 手动深拷贝更可控,避免序列化开销

















