商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > Java 一维数组深拷贝与浅拷贝的本质区别深度对比实战

Java 一维数组深拷贝与浅拷贝的本质区别深度对比实战

  发布于2026-07-04 阅读(0)

扫一扫,手机访问

要理解一维数组深拷贝和浅拷贝的区别,关键在于弄清楚一点:到底有没有复制数组里每个元素指向的对象。基本类型数组和引用类型数组在这个问题上表现截然不同——前者浅拷贝就是安全的,后者浅拷贝只是换了个数组壳子,里面装的还是同一套对象。

Ja va 一维数组深拷贝与浅拷贝的本质区别深度对比实战

基本类型数组:浅拷贝 = 安全的值拷贝

像 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、自定义类)→ 必须深拷贝,也就是逐元素新建
  • 拿不准的时候?统一按可变处理,宁可多干一步,也别留下共享隐患
本文转载于:https://www.php.cn/faq/2754066.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注