system.arraycopy对多维数组仅浅拷贝第一层引用,目标与源共享子数组对象;无法自动深拷贝,需手动逐层复制;存在类型兼容性限制和自复制重叠风险。

多维数组复制只拷贝第一层引用
System.arraycopy 对 int[][]、String[][] 这类多维数组,仅执行浅层内存拷贝:它把源数组中每个“子数组的引用”逐个复制过去,而不是递归地复制子数组内部的元素。也就是说,目标二维数组和源二维数组共享同一组子数组对象。
例如:
int[][] src = {{1,2}, {3,4}};
int[][] dst = new int[2][];
System.arraycopy(src, 0, dst, 0, 2);
此时 dst[0] 和 src[0] 指向同一个 int[] 对象,修改 dst[0][0] 会同步反映在 src[0][0] 上。
不能直接深拷贝整个多维结构
想实现真正的深拷贝(即每个子数组也全新创建并填充),System.arraycopy 本身做不到。它不识别维度语义,也不递归处理嵌套数组。你必须手动遍历每一行,对每个子数组单独调用 arraycopy 或新建并填充。
常见做法是:
- 先用 System.arraycopy 复制外层数组(即复制子数组引用)
- 再用循环 + System.arraycopy 或 Arrays.copyOf 逐个复制每个子数组内容
- 或封装成工具方法,统一处理任意维度的深拷贝逻辑
类型兼容性与运行时检查
多维数组也是引用类型,所以赋值时遵循 Java 协变规则。比如:
✔ 允许:Object[][] src = new String[2][2]; System.arraycopy(src, 0, new Object[2][], 0, 2);
✘ 报 ArrayStoreException:Integer[][] dst = new Integer[2][2]; System.arraycopy(new Number[2][2], 0, dst, 0, 2);(Number 不是 Integer 的子类)
注意:编译可能通过,但运行时类型不匹配会立即抛出异常,且已拷贝的部分不会回滚。
自复制重叠需特别小心
对多维数组做 self-copy(如 arraycopy(arr, 0, arr, 1, 2))时,若源区间与目标区间在引用层发生重叠,结果不可预测。因为 arraycopy 是按内存地址顺序拷贝,而子数组引用的写入可能覆盖尚未读取的源引用。
安全做法:
- 避免 src == dest 的多维数组自拷贝
- 如必须,先判断是否重叠;重叠时改用临时数组中转
- 或改用显式循环,控制读写顺序(如从后往前复制)











