深拷贝和浅拷贝区别

在 Java 中,**深拷贝(Deep Copy)浅拷贝(Shallow Copy)**是指对象复制时,复制的方式和结果的不同。理解这两者的区别非常重要,特别是在处理复杂对象时。浅拷贝和深拷贝的主要区别在于对象内部引用的处理方式。

1. 浅拷贝(Shallow Copy)

浅拷贝是指复制对象时,只复制对象本身,而不会复制对象内部引用的其他对象。也就是说,源对象和目标对象内部的引用类型变量(如数组、对象等)指向相同的内存地址(即它们引用的是相同的对象)。因此,源对象和目标对象共享同一份数据。

浅拷贝的特点:

  • 复制的是对象的“引用”,而非对象所指向的数据。
  • 对象的引用类型字段仍然指向原始对象的内存地址(即浅拷贝并没有创建新的引用对象)。

浅拷贝的代码示例:

class Address {
    String city;

    Address(String city) {
        this.city = city;
    }
}

class Person {
    String name;
    Address address;

    Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    // 浅拷贝方法
    public Person shallowCopy() {
        return new Person(this.name, this.address); // 复制的是引用,address 地址相同
    }
}

public class ShallowCopyExample {
    public static void main(String[] args) {
        Address address = new Address("New York");
        Person person1 = new Person("Alice", address);

        // 浅拷贝
        Person person2 = person1.shallowCopy();

        System.out.println(person1.name);        // 输出: Alice
        System.out.println(person2.name);        // 输出: Alice
        System.out.println(person1.address.city); // 输出: New York
        System.out.println(person2.address.city); // 输出: New York

        // 修改 person2 的 address
        person2.address.city = "Los Angeles";
        
        // 由于浅拷贝,person1 和 person2 的 address 是同一个对象
        System.out.println(person1.address.city); // 输出: Los Angeles
        System.out.println(person2.address.city); // 输出: Los Angeles
    }
}

输出结果

Alice
Alice
New York
New York
Los Angeles
Los Angeles

说明

  • person1person2address 引用指向相同的 Address 对象,因此修改 person2address 会影响 person1address
  • 这是因为我们进行了浅拷贝,address 字段只是引用了相同的内存地址。

2. 深拷贝(Deep Copy)

深拷贝是指复制对象时,不仅复制对象本身,而且复制对象内部引用的其他对象。也就是说,深拷贝会创建对象及其所引用的所有对象的副本,源对象和目标对象之间完全独立,它们不会共享任何引用对象。

深拷贝的特点:

  • 复制的是对象及其所有引用的对象,确保新对象的所有引用都指向新创建的对象。
  • 目标对象与源对象在内存中完全独立,修改目标对象的属性不会影响源对象。

深拷贝的代码示例:

class Address {
    String city;

    Address(String city) {
        this.city = city;
    }

    // 深拷贝方法
    public Address deepCopy() {
        return new Address(this.city);  // 创建一个新的 Address 对象
    }
}

class Person {
    String name;
    Address address;

    Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    // 深拷贝方法
    public Person deepCopy() {
        // 创建新的 Person 对象,并对 address 进行深拷贝
        return new Person(this.name, this.address.deepCopy());
    }
}

public class DeepCopyExample {
    public static void main(String[] args) {
        Address address = new Address("New York");
        Person person1 = new Person("Alice", address);

        // 深拷贝
        Person person2 = person1.deepCopy();

        System.out.println(person1.name);        // 输出: Alice
        System.out.println(person2.name);        // 输出: Alice
        System.out.println(person1.address.city); // 输出: New York
        System.out.println(person2.address.city); // 输出: New York

        // 修改 person2 的 address
        person2.address.city = "Los Angeles";
        
        // 由于深拷贝,person1 和 person2 的 address 是不同的对象
        System.out.println(person1.address.city); // 输出: New York
        System.out.println(person2.address.city); // 输出: Los Angeles
    }
}

输出结果

Alice
Alice
New York
New York
New York
Los Angeles

说明

  • person1person2address 引用指向不同的对象,person2 修改 address 不会影响 person1
  • 这是因为我们进行了深拷贝,address 字段指向了新创建的 Address 对象。

3. 深拷贝与浅拷贝的对比

特性 浅拷贝(Shallow Copy)深拷贝(Deep Copy)
引用对象的处理 只复制对象本身,不复制对象引用的其他对象。 复制对象本身及其所有引用的对象,确保每个引用指向新的对象。
对象之间的关系 源对象和目标对象共享相同的引用对象。 源对象和目标对象独立,互不影响。
修改影响 修改目标对象会影响源对象,因为它们共享同一引用对象。 修改目标对象不会影响源对象,因为它们不共享任何引用对象。
性能 浅拷贝比深拷贝更高效,因为只涉及对象本身和引用的复制。 深拷贝需要复制整个对象图,性能开销较大。

4. 深拷贝和浅拷贝的实际应用

  • 浅拷贝

    • 适用于不修改对象内部引用的情况下。比如,你只需要复制对象的基本数据,且不关心对象引用类型字段的变化。
    • 常见场景:复制对象用于某些不改变内部引用的操作,如在多线程中共享不可变的对象。
  • 深拷贝

    • 适用于需要复制对象及其引用对象,且这些引用对象的状态不应该被共享的场景。例如,修改一个对象的内部引用数据时不希望影响到其他对象。
    • 常见场景:当对象中包含嵌套的可变对象时,深拷贝能确保每个对象都被独立复制,防止修改一个对象影响到其他对象。
Java碎碎念 文章被收录于专栏

来一杯咖啡,聊聊Java的碎碎念呀

全部评论

相关推荐

评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客企业服务