Java 一维数组深拷贝与浅拷贝的本质区别深度对比实战
作者:EasyWind
时间:2026-07-04
浏览:0
一维数组深拷贝与浅拷贝的本质在于是否复制元素指向的对象。基本类型数组浅拷贝即安全值拷贝;引用类型数组浅拷贝仅复制地址,对象共享,需逐元素构造新对象实现深拷贝。元素为不可变对象时浅拷贝可用,可变对象必须深拷贝。
要理解一维数组深拷贝和浅拷贝的区别,关键在于弄清楚一点:到底有没有复制数组里每个元素指向的对象。基本类型数组和引用类型数组在这个问题上表现截然不同——前者浅拷贝就是安全的,后者浅拷贝只是换了个数组壳子,里面装的还是同一套对象。

基本类型数组:浅拷贝 = 安全的值拷贝
像 int[]、double[]、boolean[] 这类数组,里面存的就是实实在在的数值(要么在栈上,要么在堆里连续存储原始值)。这种情况下,任何标准的拷贝方式——Arrays.copyOf()、System.arraycopy()、arr.clone()——都等价于深拷贝,新旧数组在内存中完全隔离。
- 修改新数组里任意元素,原数组纹丝不动
- 不需要额外处理,用
Arrays.copyOf(arr, arr.length)就行,语义清晰、类型安全 - 千万别直接写
int[] b = a;,那只是复制了个引用,不是拷贝数组本身
引用类型数组:浅拷贝只复制“指针”,不复制“对象”
到了 String[]、User[]、Object[] 这类数组,里面存的是对象引用(说白了就是地址)。浅拷贝只把这些地址复制一遍,地址指向的实际对象一个都没动。结果是:两个数组长度一样、元素数量一样,但第 i 个位置的引用指向的是同一个堆里的对象。
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、自定义类)→ 必须深拷贝,也就是逐元素新建
- 拿不准的时候?统一按可变处理,宁可多干一步,也别留下共享隐患
作者最新文章
淘宝闪购“等灯不计时”机制解析:政策、技术与多方协同
2026-09-08 18:00
一加自研电竞三芯P4/G3/T3确认:一加16首发,支持185FPS及9000mAh电池
2026-09-08 16:52
抖音拍摄剪辑教程:从竖屏运镜到卡点成片
2026-09-03 06:05
Excel筛选大于指定数值:操作步骤与结果验证
2026-09-03 06:03
PDF添加文字水印:位置、透明度与字号设置指南
2026-09-03 06:01
上一篇:
Debian系统中如何实时监控JS日志
热门文章
更多
精品专题
更多
Mac软件
更多
WINDOWS
更多


































