System.arraycopy对引用数组执行浅拷贝——仅复制引用而非对象本身,导致可变对象共享引发数据污染;基本类型和String数组安全;二维数组存在双重浅拷贝风险;需配合手动克隆或重建实现深拷贝。

System.arraycopy 对引用数组执行的是浅拷贝——它只复制数组中每个元素的引用值,不复制这些引用所指向的对象本身。这个行为看似简单,却在实际开发中频繁引发数据污染问题,尤其当数组元素是可变对象时。
基本类型数组:天然安全,无需额外处理
int[]、double[]、boolean[] 等基本类型数组用 arraycopy 完全放心。因为复制的是数值本身,副本与原数组内存完全隔离。
- 修改 dst[i] 不会影响 src[i]
- 即使 dst 和 src 共享同一段逻辑,也不会相互干扰
- String[] 也属“安全特例”:String 不可变,引用共享无副作用
对象数组:引用复制即隐患起点
只要数组元素是自定义类、ArrayList、StringBuilder 等可变对象,arraycopy 就只搬地址,不搬内容。
- Person[] p1 = {new Person("Alice")}; Person[] p2 = new Person[1]; System.arraycopy(p1, 0, p2, 0, 1); → p1[0] 和 p2[0] 指向同一对象
- p2[0].setName("Bob") 后,p1[0].getName() 也会变成 "Bob"
- 这种共享常被误认为“复制成功”,实则是静默的数据耦合
二维数组:两层浅拷贝,风险加倍
int[][] 实际是 int[] 引用数组,arraycopy 只复制外层数组的引用,不碰内层数组内容。
- int[][] src = {{1,2}, {3,4}}; int[][] dst = new int[2][]; System.arraycopy(src, 0, dst, 0, 2); → dst[0] == src[0] 为 true
- 后续 dst[0][0] = 99 直接改写 src[0][0],原数组被意外篡改
- 若内层也是对象数组(如 Person[][]),则外层引用 + 内层引用双重共享,污染面更广
绕过局限:arraycopy 是搬运工,不是克隆器
它高效但被动——适合做深拷贝流程中的“数值搬运环节”,不能替代克隆逻辑。
- 对一维对象数组:先用 arraycopy 复制引用,再遍历调用 clone() 或 new Person(p.getName())
- 对二维基本类型数组:外层循环分配新行,内层用 arraycopy 搬数值(如示例中 dst[i] = new int[src[i].length] 后再拷贝)
- 切忌依赖 arr.clone() 或 list.clone():它们底层都调 arraycopy,仅完成外层浅拷贝

















