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. 注意事项

  1. 性能权衡:深拷贝会消耗更多内存和计算资源,需根据场景选择。
  2. 不可变对象:如果对象是不可变的(如 String),浅拷贝是安全的。
  3. 工具库:使用工具简化深拷贝:
    • Apache Commons Lang: SerializationUtils.clone(obj)
    • Gson/Jackson: 通过 JSON 序列化反序列化实现深拷贝。

总结

  • 浅拷贝:快速,但共享数据,适合基本类型或不可变对象。
  • 深拷贝:独立数据,但实现复杂,适合可变对象或需要数据隔离的场景。

根据实际需求选择拷贝方式!

posted @ 2025-03-24 18:21  bravecap  阅读(182)  评论(0)    收藏  举报