Java数组克隆本质是地址复制,非内容复制;clone()、Arrays.copyOf()、System.arraycopy()和for循环四种方式性能与适用场景各异,且默认为浅拷贝,对象数组需深拷贝才能彻底隔离。

Java 数组克隆不是“复制内容”这么简单,而是和内存分配、引用传递、JVM 原生支持深度绑定的操作。真正理解它,得从堆栈结构、引用本质和方法差异三方面入手。
数组变量只存地址,赋值不等于复制
声明 int[] arr1 = {1, 2, 3}; int[] arr2 = arr1; 后,arr2 和 arr1 指向堆中同一块内存。改 arr2[0],arr1[0] 也会变——这根本不是克隆,只是多了一个别名。
- 栈里存的是数组对象的内存地址,不是数据本身
- 所有“赋值操作”都只拷贝这个地址,不碰堆里的实际元素
- 只有新建数组并填充数据,才算真正隔离
四种主流克隆方式,底层逻辑各不同
看似效果相似,但执行路径、性能和适用场景差异显著:
-
clone():JVM 特殊优化,等价于一次
System.arraycopy(),快且简洁;仅支持一维,返回类型需强制转型(如int[] cloned = (int[]) arr.clone();) -
Arrays.copyOf():先 new 新数组,再调用
arraycopy拷贝;支持扩容/截断,多用于工具类封装 - System.arraycopy():JVM native 实现,不走 Java 解释器,直接内存搬移;参数需手动校验,适合高性能场景
- for 循环赋值:最慢但最可控,可嵌入逻辑(如过滤、转换),也便于实现二维数组的深拷贝
浅拷贝是默认行为,对象数组要特别小心
对 int[]、String[] 这类基本类型或不可变对象数组,克隆后修改元素不影响原数组——因为复制的是值或不可变引用。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
但对 Person[] 这类可变对象数组,克隆只复制对象引用,两个数组仍共享同一组 Person 实例:
- 修改
cloned[i].name,原始数组对应位置的name也会变 - 要彻底隔离,必须递归克隆每个对象(即深拷贝),或用序列化等方式重建
- 二维数组(如
int[][])本质是“对象数组”,clone()只克隆外层数组,内层数组仍共享
String 数组的克隆有迷惑性
虽然 String 不可变,String[] 克隆仍是浅拷贝。但因 String 内容不能改,所以表现像“深拷贝”:
-
strings.clone()→ 新数组 + 原引用 → 安全 -
strings[0] = "new"→ 只改引用指向,不影响其他数组 - 但若数组里存的是
StringBuilder等可变对象,风险立刻暴露

















