数组复制的关键在于区分浅拷贝(仅复制引用地址,新旧数组共享堆内存)和深拷贝(在堆中新建内存并复制数据),前者导致相互影响,后者实现完全独立;java中=赋值为浅拷贝,clone()、arrays.copyof()等对基本类型数组可实现深拷贝,但引用类型需递归处理。

数组复制不是简单地“把值搬过去”,关键在于复制时操作的是引用还是实际数据,这直接决定新旧数组是否相互影响。理解背后内存结构,才能选对复制方式。
栈中存地址,堆中存数据
Java 中声明一个数组,比如 int[] arr = new int[]{1, 2, 3};,变量 arr 本身存在栈内存里,它保存的只是一个地址(比如 0x123),真正存放 [1, 2, 3] 这三个整数的连续空间在堆内存中。复制数组,本质是处理这个地址和它指向的内容。
浅拷贝:只复制栈里的地址
像 int[] copy = arr; 这种赋值,只是把栈中 arr 的地址(0x123)又写进 copy 变量。此时两个变量指向堆中同一块内存。改 copy[0] = 99;,arr[0] 也会变成 99 —— 因为它们根本就是同一个位置。
- 适用于基本类型数组时,看起来“值一样”,但仍是共享内存
- 引用类型数组(如 String[])用这种方式,连数组元素本身都共用对象,风险更大
- 本质是“多把钥匙开同一扇门”
深拷贝:在堆里另建一套数据
要让新数组完全独立,就得在堆中申请一块新空间,把原数组每个元素的值(基本类型)或副本(引用类型)一一填进去。
- System.arraycopy() 对基本类型数组是深拷贝;对引用类型数组,只复制引用,属于浅拷贝
- 手动循环赋值、Arrays.copyOf()、clone()(对一维基本类型有效)都可实现深拷贝
- 二维或嵌套对象数组需递归拷贝,否则外层数组独立了,内层对象仍共享
常见方法对比与选择建议
不同方法在内存行为上差异明显:
- = 赋值 → 浅拷贝(地址共享)
- clone() → 一维基本类型深拷贝;引用类型仅外层深,内层浅
- System.arraycopy() → 同 clone(),高效底层调用
- Arrays.copyOf() → 封装了 arraycopy,语义更清晰
- 手动 for 循环 → 完全可控,适合需定制逻辑(如过滤、转换)的场景
不复杂但容易忽略











