本质区别在于是否复制数组中每个元素所指向的对象:基本类型数组浅拷贝即安全,因存的是值;引用类型数组浅拷贝仅复制引用地址,元素仍共享同一对象,需逐元素新建实现深拷贝。

Java一维数组的深拷贝与浅拷贝,本质区别不在“是否复制数组”,而在于“是否复制数组中每个元素所指向的对象”。基本类型数组和引用类型数组的表现截然不同——前者浅拷贝即安全,后者浅拷贝只是“换了个数组壳,里面还是同一套对象”。
基本类型数组:浅拷贝 = 安全的值拷贝
对于 int[]、double[]、boolean[] 等,数组本身存的就是数值(直接在栈或堆中连续存储原始值)。此时任何标准拷贝方式(Arrays.copyOf()、System.arraycopy()、arr.clone())都等价于深拷贝——新旧数组内存完全隔离。
- 修改新数组任意元素,原数组不受影响
- 无需额外处理,推荐使用
Arrays.copyOf(arr, arr.length)(语义清晰、类型安全) - 避免直接赋值:
int[] b = a;这只是引用复制,不是拷贝
引用类型数组:浅拷贝只复制“指针”,不复制“对象”
对于 String[]、User[]、Object[] 等,数组中存的是对象引用(地址)。浅拷贝仅复制这些地址,而非地址指向的实际对象。结果是:两个数组长度相同、元素数量一致,但第 i 个位置的引用指向同一个堆对象。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
-
User[] users1 = {new User("张三", 25)};User[] users2 = users1.clone();
此时users1[0] == users2[0]为 true - 执行
users2[0].setName("李四"),users1[0].getName()也会变成 "李四" - String[] 是特例:因 String 不可变,浅拷贝通常无副作用;但 StringBuilder[] 或自定义可变类数组必须深拷贝
真正深拷贝引用类型数组:必须逐元素构造新对象
没有通用一键方法。核心逻辑是:先创建新数组,再对每个元素调用其拷贝逻辑(克隆、构造、工厂等),确保每个元素都是独立实例。
- 若元素类实现
Cloneable并重写clone():User[] deepCopy = Arrays.stream(src).map(u -> (User) u.clone()).toArray(User[]::new); - 更推荐显式构造(类型安全、可控、免异常):
User[] deepCopy = Arrays.stream(src).map(u -> new User(u.getName(), u.getAge())).toArray(User[]::new); - 避免序列化方案(如
SerializationUtils.clone()):要求所有字段可序列化,含线程/文件句柄等资源时会失败,且性能差
怎么一眼判断该用哪种?看数组元素是否可变
关键不是“数组类型”,而是“数组里装的东西会不会被改”:
- 元素是基本类型 → 浅拷贝足够
- 元素是不可变对象(String、LocalDate、BigInteger)→ 浅拷贝足够
- 元素是可变对象(User、ArrayList、StringBuilder、自定义类)→ 必须深拷贝(即逐元素新建)
- 不确定?统一按可变处理,宁可多做一步,也不留共享隐患
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










