Java只有值传递,引用类型传的是对象地址副本;浅拷贝复制对象自身及基本类型字段、引用类型只复制地址,深拷贝则递归复制所有嵌套可变引用以彻底隔离修改。

Java 中只有值传递,但这个“值”对引用类型来说是对象地址的副本。理解这点,才能看清为什么浅拷贝和深拷贝不是可选技巧,而是应对值传递副作用的必要手段。
值传递的本质决定拷贝的必要性
方法参数传入对象时,传递的是堆中对象地址的一个拷贝。形参和实参指向同一块内存——修改对象字段(如 user.setName("Tom"))会影响原对象;但让形参指向新对象(如 user = new User())不会改变实参指向。这种“地址副本”的行为,正是浅拷贝默认生效的基础,也是深拷贝必须介入的起点。
- 基本类型参数:传的是真实数值副本,改它不影响原变量
- 引用类型参数:传的是地址副本,改它指向的对象内容,就等于改了原对象
- 不拷贝直接复用对象:在异步、缓存、校验等场景极易引发数据污染
浅拷贝解决一层引用共享问题
浅拷贝复制对象自身字段,对基本类型赋值,对引用类型只复制地址。适用于对象结构扁平、内部引用多为不可变类型(如 String、Integer、LocalDateTime)的场景。
- 用
new ArrayList(original)创建新 List,避免集合被意外 add/remove - 实现
Cloneable并重写clone(),注意调用super.clone()返回本类实例 - 拷贝构造函数最可控:
public Student(Student other) { this.name = other.name; this.age = other.age; this.address = other.address; }——注意此时address仍是引用共享
深拷贝切断全部层级的引用链
当对象含嵌套可变引用(如 Student 里有 Address,Address 又含 List<phone></phone>),浅拷贝无法隔离修改。深拷贝需递归复制每一层引用对象,确保原始对象与副本完全独立。
立即学习“Java免费学习笔记(深入)”;
- 手动递归拷贝:适合结构稳定、嵌套不深的业务对象,控制力强但易漏字段
- 序列化方式(
Serializable):通用性强,要求所有嵌套类都可序列化,有反射开销,不支持 transient 字段 - JSON 工具中转(如 Jackson、Gson):代码简洁,天然跳过 transient 和静态字段,但依赖 JSON 序列化逻辑,可能丢失类型信息或精度(如
BigDecimal)
什么时候该用哪一种?看数据生命周期和变更风险
不是越深越好,关键是匹配使用场景:
- 仅需隔离集合容器本身(如传参后要 clear/add)→ 浅拷贝足矣
- 对象将被异步处理、缓存复用或跨模块流转 → 必须深拷贝,尤其含可变集合或自定义引用类型时
- 性能敏感且对象简单(如 DTO 全是 String/Long)→ 浅拷贝 + 不可变语义 ≈ 安全深拷贝
- 无法修改源类(如第三方 jar 中的类)→ 优先选 JSON 或序列化方案,绕过
Cloneable限制


















