System.arraycopy不支持二维数组的深层复制,仅复制引用;对int[][]等基本类型需循环配合arraycopy逐行复制数值,对对象类型还需深克隆元素;String[][]因不可变性可浅拷贝,拼接或局部搬运时须注意子数组初始化与语义区分。

System.arraycopy 本身不理解“二维数组”这个概念,它只按一维方式搬运内存块。Java 中的二维数组(如 int[][])本质是一个一维引用数组,每个元素指向一个独立的一维数组对象。这种结构决定了 arraycopy 在处理时极易引发意料之外的共享行为。
复制整张二维表时,默认只复制行引用
当你对 int[][] src 和 int[][] dst 直接调用 System.arraycopy(src, 0, dst, 0, src.length),实际复制的是 src[0]、src[1]… 这些一维数组的引用,而不是它们内部的数值。结果是 dst[i] == src[i] 为 true —— 两套“表头”指向同一组“行数据”,改任意一行都会同步影响双方。
基本类型行内拷贝安全,对象类型必须逐层深处理
- 若二维数组元素是
int、double等基本类型,可用循环 + arraycopy 安全复制每行内容:先为dst[i]分配新数组,再用 arraycopy 拷贝数值 - 若元素是可变对象(如
Person[]或StringBuilder[]),仅复制行引用还不够;还需对每行中每个对象单独克隆或重建实例 - String[][] 是个特例:String 不可变,浅拷贝不会导致数据污染,但逻辑上仍属引用共享
拼接多个二维数组容易踩坑
想把 a[][] 和 b[][] 合并成一个更大的二维数组,不能直接用 arraycopy 拼接两个 Object 引用数组。正确做法是:先计算总行数,新建目标二维数组,再逐行分配子数组并用 arraycopy 复制内容。若忽略子数组初始化,运行时会抛 NullPointerException。
局部行搬运需明确目的:换引用还是搬数值
把第 i 行内容“搬到”第 j 行,有两种语义:
- 让
grid[j] = grid[i]→ 直接赋值即可,arraycopy 多余 - 把
grid[i]的所有数值写入已存在的grid[j]→ 才需要System.arraycopy(grid[i], 0, grid[j], 0, grid[i].length) - 后者对基本类型安全,对对象类型仍只复制引用;若要避免副作用,必须确保
grid[j]已指向独立对象,且其元素也已深拷贝

















