Java数组clone()是浅拷贝:基本类型数组独立,对象数组共享引用;深拷贝应权衡性能,优先用不可变对象或DiffUtil等轻量方案;System.arraycopy()最快,clone()最慢。

Clone 本身不深,别被名字骗了
Java 数组的 clone() 方法对基本类型数组(如 int[]、byte[])确实生成独立副本,改新数组不影响原数组——这常被误认为“深拷贝成功”。但对对象数组(如 String[]、Person[]),clone() 只复制引用,不是对象本身。结果是两个数组共享同一组实例,修改 cloned[0].name,original[0].name 立刻同步变化。这不是 bug,是设计使然:clone 是浅拷贝,语义清晰,性能代价低,但绝不等于“数据隔离”。
真要深拷贝?先问值不值得
多数场景下,强行深拷贝反而是性能负担和隐患源头:
- 序列化+反序列化(如
ObjectOutputStream写入再读出)虽能实现完整深拷贝,但耗时高、有安全限制、跳过transient字段,且对大数组可能触发 GC 压力; - 手写递归 clone(每个对象字段都显式调用
.clone())逻辑复杂、易漏、维护成本高; - 更轻量的替代方案往往更优:用不可变对象(
String、LocalDateTime、自定义final类),或构造新对象替代修改原对象,从源头避免共享状态。
高性能场景下的内存优化技巧
克隆动作本身开销小,真正吃内存的是“不该克隆时克隆”和“克隆方式选错”:
- 避免在循环中反复克隆同一数组(比如每次请求都
template.clone()),改为启动时克隆一次,复用副本; - 百万级
float[]直接 clone 会瞬占几十 MB 堆内存,可改用分块处理、MemorySegment视图或Arrays.spliterator()流式计算,避免全量驻留; - Android 中
RecyclerView数据更新,别每次都 clone 整个List<t></t>,用DiffUtil算最小差异集,只更新变动项。
选对方式,比盲目克隆更重要
四种主流数组复制方式性能与适用性差异明显:
立即学习“Java免费学习笔记(深入)”;
-
System.arraycopy():JVM 底层优化,绕过边界检查、支持 SIMD 向量化,速度最快,适合中大型数组(数千元素起);需手动创建目标数组,类型长度必须匹配; -
Arrays.copyOf():内部调用arraycopy,但多了扩容/截断逻辑和新数组分配,比前者慢 10–20%,胜在简洁; -
clone():一行代码,语义明确,但实测速度仅达arraycopy的 1/9–1/10,尤其在大字节数组场景; - for 循环:小数组(≤4 元素)可能略快,但随长度增长性能快速下滑;唯一支持边复制边转换(过滤、映射、类型适配)的方式。



















