Java数组clone()是JVM专设高效原语,不走Object.clone()反射路径,跳过Cloneable检查与异常抛出,直接内存块复制,类型保留、线程安全、性能近System.arraycopy()。

Java 数组的 clone() 不是普通对象的浅拷贝,而是 JVM 专设的高效原语操作——它不走 Object.clone() 的反射路径,也不检查 Cloneable 接口,更不抛异常,而是直接按内存块复制,类型保留、线程安全、性能接近 System.arraycopy()。
数组 clone 是 JVM 内置的特殊指令
当你写 int[] b = a.clone();,JVM 并不会解析成调用 Object.clone() 的通用逻辑。字节码中虽是 invokespecial java/lang/Object.clone,但虚拟机在运行时识别出操作对象是数组类型,立刻绑定到内部专用克隆例程。这个过程:
- 跳过
Cloneable接口检查(数组类自动“被认为”可克隆) - 绕过字段级反射复制,不访问任何 Java 层构造或初始化逻辑
- 直接触发底层内存复制指令(如平台优化的 SIMD 或
memcpy等效) - 保证新数组与原数组类型完全一致(
String[]克隆后仍是String[],不是Object[])
基本类型数组克隆 = 值拷贝,效果等同深拷贝
对 int[]、double[] 等基本类型数组,clone() 复制的是每个元素的实际值。由于基本类型没有引用语义,这种复制天然隔离:
- 修改原数组元素,不影响克隆数组
- 修改克隆数组元素,也不影响原数组
- 无需额外处理,开箱即用,安全可靠
引用类型数组克隆仍是浅拷贝
对于 String[]、Person[] 这类引用数组,clone() 只复制数组本身和其中每个引用地址,不递归克隆元素对象:
立即学习“Java免费学习笔记(深入)”;
- 新旧数组是两个独立对象(
a != b) - 但
a[0] == b[0]成立(指向同一String实例) - 若元素是可变对象(如
StringBuilder[]),修改b[0].append("x")会影响a[0]
为什么不用手动循环或 arraycopy?
虽然 System.arraycopy() 功能相近,但 clone() 有不可替代优势:
-
类型安全返回:返回具体数组类型,无需强制转型(
int[]→int[],而非Object) - 原子性保障:整个复制过程由 JVM 控制,在返回前已完全构造完毕,不存在中间态
-
零配置可用:无需 import、无需 try-catch(数组永远可克隆,不抛
CloneNotSupportedException) -
语义清晰:
a.clone()比Arrays.copyOf(a, a.length)更直观表达“我要副本”意图


















