Java引用类型数组默认浅拷贝,仅复制对象地址而非实例,修改任一数组元素会影响另一数组;深拷贝需手动重建对象,如用clone()、复制构造函数或序列化。

Java里拷贝引用类型数组,表面看是复制了元素,实际只复制了对象地址——改一个,两个数组都跟着变。这不是bug,是浅拷贝的正常表现,关键在于你是否意识到并主动应对。
引用类型数组默认都是浅拷贝
无论用 System.arraycopy()、Arrays.copyOf() 还是 clone(),只要数组元素是自定义对象(如 Person、User),拷贝后新旧数组里的元素都指向堆中同一组对象。
- 修改 copy[0].name,original[0].name 也会变
- 这跟基本类型(int、boolean)完全不同——后者拷贝的是实实在在的值
- 赋值语句
arr2 = arr1更极端:连新数组都不创建,只是多了一个指向原数组的引用
需要深拷贝时,得手动重建对象
深拷贝的本质,是为每个对象创建独立副本。没有通用一键方法,但有清晰路径:
- 遍历原数组,对每个对象调用其 clone() 方法(前提是该类已实现
Cloneable并重写clone()) - 或用构造函数重建:
new Person(p.getName(), p.getAge()) - 或借助序列化(适合可序列化的简单对象,但性能开销大,不推荐高频场景)
选对工具,避免踩坑
不同场景下,方法选择直接影响代码健壮性:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
立即学习“Java免费学习笔记(深入)”;
- 只读或临时传递:用
Arrays.copyOf()最省事,语义清晰 - 需部分复制或插入到已有数组:
System.arraycopy()灵活可控,比如合并游戏怪物列表 - 想快速获得同类型新数组且不关心后续修改:
clone()可行,但仍是浅拷贝,别误以为它能隔离对象 - 绝对不能直接用
=赋值来“拷贝”,那只是共享引用,风险极高
一个实用的深拷贝小技巧
如果对象结构简单、字段不多,推荐在类里加一个复制构造函数:
class Person {String name;
int age;
Person(Person p) {
this.name = p.name;
this.age = p.age;
}
}
然后拷贝时写:Person[] deepCopy = Arrays.stream(original).map(Person::new).toArray(Person[]::new); ——逻辑直白,不易出错。

















