浅拷贝是复制数组容器及元素引用地址,基本类型值被复制,引用类型共享对象实例;它高效安全,适用于基本类型数组传递、只读视图缓存和不可变包装结构等场景。

Java数组拷贝中,“浅拷贝”不是低效的代名词——它恰恰是大多数场景下最高效、最安全的选择,前提是理解它的行为边界。关键不在于“要不要深”,而在于“什么时候只需浅”。
什么是浅拷贝:复制引用,而非对象
浅拷贝只创建新数组容器,元素本身不重新构造。对基本类型(如 int、boolean),值被真实复制;对引用类型(如 String、自定义对象、List),复制的是内存地址,新旧数组指向同一堆对象。
- int[] arr1 = {1, 2, 3}; int[] arr2 = arr1.clone(); → 修改 arr2[0] 不影响 arr1 → 因为 int 是值类型
- Person[] p1 = {new Person("A")}; Person[] p2 = p1.clone(); → p1[0] == p2[0] 为 true → 因为 Person 是引用,地址被复制
- 二维数组 int[][] mat = {{1,2}}; int[][] copy = mat.clone(); → copy[0] == mat[0] → 外层数组新,内层数组仍共享
四种主流浅拷贝方式及适用场景
不同写法性能与可读性略有差异,但本质一致:不穿透引用层级。
- Arrays.copyOf(arr, len):推荐首选。语义清晰,内部调用 System.arraycopy,JVM 优化充分,支持泛型推导(如 String[])
- arr.clone():轻量直接,无需 import,但返回 Object 类型需强转(如 (String[]) arr.clone())
- System.arraycopy(src, 0, dst, 0, len):底层控制力最强,适合复用已有目标数组、避免新建对象,或在循环中批量拷贝
- for 循环赋值:显式可控,便于插入逻辑(如过滤、转换),但代码略冗长,JVM 无法做批量内存优化
避坑指南:这些“看似深”的操作仍是浅拷贝
开发者常误以为某些写法实现了深隔离,实则仍共享引用,修改子对象会相互干扰。
- Arrays.copyOf() 用于对象数组 → 元素引用未变,Person[] 拷贝后改 name,原数组同步变
- ArrayList 构造函数 new ArrayList(list) → 底层仍是浅拷贝,list 中的 Person 对象仍共用
- 多维数组 clone() 或 Arrays.copyOf() → 只复制第一层引用,int[][] 的每一行仍是同一数组实例
- String 类型看似安全 → 实际因不可变性“表现像深拷贝”,但本质仍是引用复制,只是无法被修改
何时该用浅拷贝:三个典型高效场景
浅拷贝的价值,在于它不做多余工作。以下情况选它既快又稳:
- 基本类型数组批量读取/传递:如 int[] 作为参数传入工具方法,防止被意外修改,开销仅 O(1) 内存分配 + O(n) 内存复制
- 临时缓存只读视图:如将数据库查询结果转成 String[] 后供 UI 层展示,后续不修改内容,clone 即可隔离原始数据源
- 构建不可变包装结构:配合 final 字段使用,例如 public final String[] names = Arrays.copyOf(src, src.length); 确保外部无法通过引用篡改内部状态
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











