java数组拷贝本质是堆内存地址管理:栈中变量仅存堆地址,arr2 = arr1只是地址复制,共享同一堆空间;真拷贝需arrays.copyof、system.arraycopy、clone或循环新建堆空间,基本类型拷贝即隔离,对象数组才需区分浅拷贝与深拷贝。

Java数组拷贝不是复制“数据本身”,而是管理“堆中那块连续内存”的访问权。真正决定是否独立、是否安全的,是变量指向哪——栈里存的是地址,堆里才是真数据。
数组在内存里怎么存?栈和堆分工明确
声明 int[] arr = {1, 2, 3}; 时:
- 变量 arr 存在栈中,它只是一个4字节或8字节的地址值(比如
@4d41cee) - 实际元素
1, 2, 3连续存放在堆内存某块区域,由 arr 指向 - 这种连续布局让
arr[i]能用公式首地址 + i × 4直接定位,所以随机访问快
为什么 arr2 = arr1 不叫拷贝?
这行代码只做了地址复制,两个变量共享同一块堆内存:
- 修改
arr2[0] = 99,arr1[0]立刻变成 99 - 打印
arr1和arr2的哈希码(System.identityHashCode()),结果相同 - 这不是“复制失败”,而是设计如此——Java 所有引用类型赋值都这样
四种真拷贝方式,各干各的活
要获得新堆空间里的独立副本,必须显式创建并搬运内容:
-
Arrays.copyOf(arr, len):最常用。自动 new 新数组,内部调用
System.arraycopy;支持类型转换(如int[] → long[]) - System.arraycopy(src, 0, dst, 0, len):JVM 底层指令级搬运,零额外开销;支持部分拷贝、原数组内移位(比如删除后前移)
- arr.clone():数组原生方法,返回新数组;对基本类型完全隔离,对象数组仍是浅拷贝
- 手动循环:语义清晰,适合带条件过滤、转换逻辑;但性能最低,仅用于教学或特殊场景
深拷贝只在对象数组里才有意义
基本类型数组(int[]、double[])拷贝即隔离,不存在“深浅”之分:
- 对象数组(
String[]、Person[])才需区分: - 浅拷贝(
Arrays.copyOf或clone):新数组每个元素仍指向原对象,改对象内容会互相影响 - 深拷贝需递归克隆每个对象,比如
Person内部的Address也要新建并复制字段 - 二维数组本质是“一维数组里存一维数组引用”,深拷贝必须逐层处理:先拷贝外层数组,再遍历拷贝每个内层数组
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











