Java数组无真正深拷贝,clone()等默认浅拷贝:基本类型数组效果等同深拷贝,引用类型需递归拷贝元素;二维数组需嵌套clone;通用方案优先选Hutool序列化克隆。

Java 数组本身不支持真正的深拷贝,因为 clone()、Arrays.copyOf() 等方法默认只做浅拷贝——对基本类型数组(如 int[]、double[])效果等同深拷贝,但对引用类型数组(如 String[]、Person[]),仅复制元素引用,不复制元素对象本身。所谓“数组深拷贝”,本质是:先拷贝数组容器,再递归拷贝每个元素对象。方案选择取决于数组元素类型和性能要求。
基本类型数组:clone() 就够用,且最简洁
对于 int[]、long[]、boolean[] 等纯基本类型数组,clone() 是安全、高效、零配置的首选:
-
int[] a = {1, 2, 3}; int[] b = a.clone();→b是独立副本,修改b[0]不影响a - 底层调用 JVM 原生实现,性能接近
System.arraycopy,比Arrays.copyOf更轻量 - 无需额外依赖,无序列化开销,不抛异常,语义清晰
一维引用类型数组:需逐元素深拷贝
String[] 看似不可变,但仍是引用类型;Person[] 等自定义对象数组更需谨慎。此时 clone() 只复制引用,不是真正隔离:
-
String[] a = {"a", "b"}; String[] b = a.clone(); b[0] = "x";→a不变(因String不可变),但这是巧合,非深拷贝保证 - 若元素是可变对象(如
StringBuilder[]或自定义Address[]),必须手动遍历并调用每个元素的clone()或构造新实例 - 推荐写法:
Person[] copy = Arrays.stream(original).map(Person::clone).toArray(Person[]::new);(前提是Person实现了深克隆逻辑)
二维及以上数组:clone() 仅浅层,必须嵌套处理
二维数组如 int[][] 实际是“引用数组的数组”,clone() 只复制外层数组引用,内层数组仍共享:
立即学习“Java免费学习笔记(深入)”;
-
int[][] a = {{1,2}, {3,4}}; int[][] b = a.clone(); b[0][0] = 999;→a[0][0]也会变成999(因b[0]和a[0]指向同一数组) - 安全做法:外层
clone()+ 内层循环clone():int[][] b = Arrays.stream(a).map(int[]::clone).toArray(int[][]::new); - 对
Object[][],还需确保每个Object元素自身支持深拷贝(如实现Cloneable或提供静态deepCopy()方法)
通用高性能替代方案:避免反射与序列化陷阱
当数组元素类型复杂、不确定或无法修改源码时,通用深拷贝需权衡性能与适用性:
-
优先用 Hutool 的
ObjectUtil.cloneByStream(obj):基于 JDK 序列化,要求所有元素实现Serializable,适用广,但有反序列化开销,百万级数据下比原生clone慢 3–5 倍 -
避免 JSON 方案(如 Jackson
copyToValue()):字符串编解码成本高,且丢失泛型、瞬态字段、循环引用处理复杂,仅适合调试或小数据 - 慎用反射克隆:虽可绕过接口约束,但性能不稳定、易受访问控制限制,且无法处理 final 字段或私有构造逻辑



















