java数组clone()默认浅拷贝:基本类型数组效果等同深拷贝,因值复制且互不影响;引用类型数组仅复制引用,修改对象状态会相互影响,需手动遍历、序列化或json转换实现真正深拷贝。

Java 中数组的 clone() 方法默认执行的是浅拷贝,但对基本类型数组和引用类型数组的表现效果不同:前者行为等效于深拷贝,后者仍是典型浅拷贝。
基本类型数组调用 clone() 是安全的深拷贝效果
基本类型(如 int、double、boolean 等)本身不涉及对象引用,值直接存储在栈或数组连续内存中。调用 array.clone() 会创建一个新数组,每个元素按值复制,两个数组完全独立。
- 修改原数组任意元素,不会影响克隆数组
- 修改克隆数组任意元素,也不会反向影响原数组
- 底层由 JVM 优化实现,性能接近 System.arraycopy()
引用类型数组调用 clone() 仍是浅拷贝
数组元素是对象引用(如 String[]、Person[]、Integer[]),clone() 只复制引用地址,不复制堆中实际对象。结果是两个数组持有相同对象的引用。
- 若修改数组中某个元素的引用(如
arr1[i] = new Person()),不影响另一个数组 —— 因为只是改了“指针” - 若通过任一数组访问并修改对象内部状态(如
arr1[0].setName("Alice")),另一数组看到的也是同一对象的新状态 - 常见陷阱:误以为 clone() 对对象数组做了深拷贝,导致并发或逻辑错误
验证 clone() 行为的典型代码片段
对比基本类型与引用类型:
-
int[]:
int[] a = {1,2,3}; int[] b = a.clone(); b[0] = 999;→ a 仍为 [1,2,3] -
String[]:
String[] x = {"a","b"}; String[] y = x.clone(); y[0] = "z";→ x 不变(因重新赋值引用),但y[1] = null;同样不影响 x -
自定义对象数组:
Person[] p1 = {new Person("Tom")}; Person[] p2 = p1.clone(); p2[0].name = "Jerry";→ p1[0].name 也变成 "Jerry"
需要真正深拷贝时该怎么办
如果目标是让数组及其所有元素对象都完全独立,不能依赖 clone()。可行方案包括:
- 对引用类型数组,手动遍历并调用每个元素的 clone()(前提是该类正确实现了深克隆逻辑)
- 使用序列化(如 ByteArrayOutputStream + ObjectInputStream)绕过引用共享
- 借助 Gson 或 Jackson 库:先 toJson 再 fromJson,天然规避引用关系
- 构造新对象数组,显式 new 并复制字段(适合结构简单、可控场景)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











