System.arraycopy仅执行浅拷贝,不解决数据污染;基本类型数组和String[]安全,对象数组及多维数组需手动深拷贝,arraycopy仅可作为深拷贝中的高效搬运工具。

System.arraycopy 本身不做深拷贝,它只负责高效搬运内存块。所谓“解决数据污染”,其实是认清它只做浅拷贝,并在该用深拷贝的地方主动绕开它、补足逻辑。
一、先分清什么时候是真安全(无需深拷贝)
基本类型数组(int[]、double[]、boolean[] 等)用 arraycopy 是安全的——复制的是数值本身,改副本不影响原数组。
- 例如:
int[] src = {1, 2, 3}; int[] dst = new int[3]; System.arraycopy(src, 0, dst, 0, 3);→ 修改dst[0] = 99,src完全不变 - String[] 也通常安全:因为 String 不可变,即使引用共享,也无法通过修改影响对方
二、识别高危场景:对象数组和多维数组
只要数组元素是可变对象(如 ArrayList、自定义类实例、StringBuilder),或数组本身是二维(int[][]、String[][]),arraycopy 就只复制引用,不复制对象内容。
-
Person[] p1 = {new Person("Alice")}; Person[] p2 = new Person[1]; System.arraycopy(p1, 0, p2, 0, 1);→p1[0] == p2[0]为 true;改p2[0].name,p1[0].name同步变 -
int[][] grid = {{1,2}, {3,4}}; int[][] copy = new int[2][]; System.arraycopy(grid, 0, copy, 0, 2);→copy[0] == grid[0],仍是同一数组对象
三、需要深拷贝时,arraycopy 只能当“搬运工”,不能当“克隆器”
它可加速子步骤,但不能替代深拷贝逻辑。正确做法是:先分配新结构,再用 arraycopy 搬数值/引用,最后对每个可变元素单独克隆。
- 对一维对象数组:先新建目标数组,用 arraycopy 复制引用,再遍历调用
clone()或构造新实例 - 对二维数组:需两层循环 —— 外层分配新行数组,内层用 arraycopy 拷贝每行内容(若元素是基本类型);若行内也是对象,则每行还要逐个深拷贝
- 示例(二维 int[][] 深拷贝):
int[][] src = {{1,2},{3,4}};
int[][] dst = new int[src.length][];
for (int i = 0; i dst[i] = new int[src[i].length];
System.arraycopy(src[i], 0, dst[i], 0, src[i].length); // 这里才真正安全
}
四、警惕“伪深拷贝”惯用写法
别误以为 list.clone() 或 arr.clone() 是深拷贝——它们底层都调了 arraycopy,只复制外层数组,对元素或子数组完全不处理。
-
ArrayListlist = new ArrayList(); list.add(new StringBuilder("a")); ArrayList→copy = (ArrayList ) list.clone(); copy.get(0).append("b")会同时改变list.get(0) - 想真正隔离,必须:
new ArrayList(list.stream().map(sb -> new StringBuilder(sb)).collect(Collectors.toList())),或手动遍历构造










