数组无需实现cloneable接口即可克隆,因jvm自动将其视为cloneable;clone()是native浅拷贝,基本类型独立,引用类型共享对象;深克隆需手动处理或序列化。

数组克隆本身不依赖 Cloneable 接口,但 Java 中所有数组类型(如 int[]、String[]、Person[])在 JVM 层面被**自动视为实现了 Cloneable 接口**。这是数组的特殊待遇,和普通类必须显式 implements Cloneable 有本质区别。
为什么数组不用写 implements Cloneable 就能 clone?
Java 规范明确规定:数组类型是“天然可克隆”的。JVM 在创建数组实例时,会为其隐式赋予 Cloneable 身份。因此,调用 array.clone() 不会抛出 CloneNotSupportedException,哪怕你没写任何接口声明。
-
底层机制:数组的
clone()是 JVM 内置支持的 native 操作,直接按字节复制内存块(基本类型)或引用地址(对象类型),效率极高。 -
验证方式:你可以执行
new String[0].getClass().isAssignableFrom(Cloneable.class)或更直接地new String[0] instanceof Cloneable,结果都是true。 -
注意边界:这个“免接口”特权仅限于数组类型本身;如果你封装数组到一个自定义类(如
MyList),那该类仍需显式实现Cloneable并重写clone()才能被外部克隆。
数组 clone() 默认是浅克隆
无论元素是基本类型还是引用类型,array.clone() 都只做一层拷贝:
-
基本类型数组(如
int[]):每个数值被完整复制,新旧数组完全独立,互不影响。 -
引用类型数组(如
String[]、Person[]):数组容器被复制,但每个元素仍是原对象的**同一引用**。修改cloneArr[0].setName("X"),会影响原数组中对应对象的状态。 -
多维数组(如
int[][]):只克隆最外层数组,内层数组仍是共享引用。例如matrix.clone()[0] == original[0]为true。
如何对数组做深克隆?
Java 没有内置的数组深克隆方法,需手动处理引用类型元素:
-
一维对象数组:遍历并逐个调用元素的
clone()(要求元素类已正确实现深克隆逻辑)或使用构造器/复制构造函数重建。 -
二维及以上数组:嵌套循环 + 每层调用
clone(),或借助工具类(如 Apache Commons Lang 的ArrayUtils.deepClone(),它对常见类型做了适配)。 - 通用安全方案:序列化反序列化(要求所有元素可序列化),或使用 JSON 工具(如 Jackson)先转字符串再解析,虽稍重但能彻底隔离引用。
与 ArrayList 克隆的关键区别
别把数组和 ArrayList 混为一谈:
-
ArrayList的clone()方法是重写的浅克隆,返回的是Object,需强制转型;它克隆的是内部Object[] elementData,同样不递归克隆元素。 - 数组的
clone()是语言级能力,返回类型与原数组一致(协变返回),无需转型,也不依赖集合框架。 - 二者都只是“容器浅拷”,真正决定是否深拷的,永远是元素本身的性质和你是否主动干预。











