java数组深浅拷贝
在 Java 中,浅拷贝(Shallow Copy)和深拷贝(Deep Copy)是数据拷贝时的核心概念,尤其在处理对象数组或嵌套对象时容易引发问题。以下是详细解释和示例:
1. 浅拷贝(Shallow Copy)
定义:仅复制对象的引用(内存地址),不复制对象本身。拷贝后的对象与原对象共享内部数据。
- 适用场景:拷贝基本类型数组,或不需要独立修改对象内容的场景。
- 问题:如果数组元素是对象,修改拷贝后的数组会影响原数组!
示例:对象数组的浅拷贝
class Person {
String name;
Person(String name) { this.name = name; }
}
Person[] src = { new Person("Alice"), new Person("Bob") };
Person[] dest = Arrays.copyOf(src, src.length); // 浅拷贝
// 修改拷贝后的数组元素
dest[0].name = "Charlie";
// 原数组也被修改!
System.out.println(src[0].name); // 输出 "Charlie"
2. 深拷贝(Deep Copy)
定义:完全复制对象及其内部数据,生成独立的新对象。拷贝后的对象与原对象无任何关联。
- 适用场景:需要完全独立的副本,避免共享数据。
实现深拷贝的方法
方法 1:手动复制对象
Person[] dest = new Person[src.length];
for (int i = 0; i < src.length; i++) {
// 创建新对象,复制原对象的属性
dest[i] = new Person(src[i].name);
}
// 修改拷贝后的数组不会影响原数组
dest[0].name = "David";
System.out.println(src[0].name); // 输出 "Charlie"(原数组未变)
方法 2:实现 Cloneable 接口
class Person implements Cloneable {
String name;
Person(String name) { this.name = name; }
@Override
public Person clone() {
try {
return (Person) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
// 使用 clone() 方法深拷贝
Person[] dest = new Person[src.length];
for (int i = 0; i < src.length; i++) {
dest[i] = src[i].clone();
}
方法 3:序列化(需要对象实现 Serializable)
import java.io.*;
public static <T> T deepCopy(T obj) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
oos.flush();
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (T) ois.readObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 使用示例
Person[] dest = deepCopy(src);
3. 深浅拷贝对比
| 特性 | 浅拷贝 | 深拷贝 |
|---|---|---|
| 复制内容 | 仅复制引用 | 复制对象及其所有子对象 |
| 内存占用 | 低(共享数据) | 高(独立数据) |
| 修改影响 | 影响原对象 | 不影响原对象 |
| 实现复杂度 | 简单(如 System.arraycopy) |
复杂(需逐层处理或序列化) |
4. 多维数组的拷贝问题
对于多维数组(如 int[][] 或对象数组的数组),默认拷贝方法仅浅拷贝外层数组:
int[][] src = { {1, 2}, {3, 4} };
int[][] dest = Arrays.copyOf(src, src.length);
// 修改子数组会影响原数组!
dest[0][0] = 99;
System.out.println(src[0][0]); // 输出 99
深拷贝多维数组需逐层处理:
int[][] dest = new int[src.length][];
for (int i = 0; i < src.length; i++) {
dest[i] = Arrays.copyOf(src[i], src[i].length);
}
5. 注意事项
- 性能权衡:深拷贝会消耗更多内存和计算资源,需根据场景选择。
- 不可变对象:如果对象是不可变的(如
String),浅拷贝是安全的。 - 工具库:使用工具简化深拷贝:
- Apache Commons Lang:
SerializationUtils.clone(obj) - Gson/Jackson: 通过 JSON 序列化反序列化实现深拷贝。
- Apache Commons Lang:
总结
- 浅拷贝:快速,但共享数据,适合基本类型或不可变对象。
- 深拷贝:独立数据,但实现复杂,适合可变对象或需要数据隔离的场景。
根据实际需求选择拷贝方式!

浙公网安备 33010602011771号