Java数组深拷贝需分情况:基本类型数组用clone()或Arrays.copyOf即可;引用类型数组需手动遍历构造新实例或序列化反序列化;二维数组需逐层clone;框架如SerializationUtils或MapStruct可简化复杂场景。

Java 数组的深拷贝不是简单调用 clone() 就能解决的事。基本类型数组(如 int[])用 clone() 是安全的,但引用类型数组(如 User[]、List[])只做浅拷贝——新数组和原数组元素指向同一堆对象,改一个,另一个也跟着变。
Clone 机制对数组的实际效果
clone() 对一维数组是“半深拷贝”:它会创建新数组容器,但数组里的每个元素只是复制引用。这本质上仍是浅拷贝逻辑。
- 对
int[] arr = {1, 2, 3};:调用arr.clone()得到的是真正独立的新数组,修改副本不影响原数组 - 对
User[] users = {new User("A"), new User("B")};:调用users.clone()后,新数组和原数组长度、索引位置一致,但users[0]和cloned[0]指向同一个User实例 - 二维数组(如
int[][])更需警惕:matrix.clone()只复制第一层引用,子数组仍共享;必须手动遍历每一行再clone()
手写深度拷贝:适用简单结构
当数组元素类型可控、层级不深时,可直接在业务代码中实现递归克隆,无需引入框架。
- 基本类型数组:直接用
Arrays.copyOf(arr, arr.length)或arr.clone()即可 - 单层引用数组:遍历 + 构造新实例,例如
User[] cloned = Arrays.stream(original).map(u -> new User(u.getName(), u.getId())).toArray(User[]::new); - 含嵌套对象的数组:若
User内部有Address address,则需确保Address也支持克隆(如实现Cloneable并重写clone()),并在User.clone()中显式调用address.clone()
序列化反序列化:通用但有约束
这是最“无脑”实现深拷贝的方式,只要整个对象图可序列化(所有类及字段都实现 Serializable),就能一次完成完全隔离的副本。
立即学习“Java免费学习笔记(深入)”;
- 优点:自动处理任意嵌套层级,不依赖对象是否实现
Cloneable - 缺点:性能开销大(IO + 反射)、不能序列化
transient字段或非Serializable类型(如Thread、Socket)、需处理IOException和ClassNotFoundException - 示例:将数组包装进可序列化容器,通过
ObjectOutputStream→ByteArrayOutputStream→ObjectInputStream完成拷贝
深度拷贝框架(如 Apache Commons Lang、MapStruct、Dozer)
这些工具适合中大型项目,尤其当对象结构复杂、需频繁拷贝且难以统一改造模型类时。
-
Commons Lang 的
SerializationUtils.clone():底层就是序列化方案,封装了异常和流操作,用法极简,但仍有相同限制 - MapStruct:面向 DTO 转换设计,通过注解生成高效字节码,不走反射也不依赖序列化,性能好、类型安全,但需定义映射接口,不适合临时数组拷贝
- 注意:像 Gson、Jackson 这类 JSON 序列化器也能间接实现深拷贝(转 JSON 再解析),但会丢失类型信息、忽略不可序列化字段、无法处理循环引用,仅作临时调试可用


















