问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

一文彻底搞懂深拷贝和浅拷贝的区别

创作时间:
作者:
@小白创作中心

一文彻底搞懂深拷贝和浅拷贝的区别

引用
CSDN
1.
https://blog.csdn.net/weixin_44772566/article/details/136515491

在Java编程中,深拷贝和浅拷贝是两个非常重要的概念,它们决定了对象复制时的行为。本文将通过详细的讲解和代码示例,帮助读者彻底理解深拷贝和浅拷贝的区别。

1. 主要区别

深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是在复制对象或数据结构时所使用的两种不同的拷贝方法,它们之间的区别主要在于拷贝的程度和对原始对象内部结构的影响。

1.1 浅拷贝(Shallow Copy)

  • 浅拷贝创建一个新的对象,但是只复制原始对象的基本数据类型的字段或引用(地址),而不复制引用指向的对象。这意味着新对象和原始对象中的引用指向相同的对象。
  • 如果原始对象中的字段是基本数据类型,那么这些字段会被复制到新对象中,而如果字段是引用类型,则新对象和原始对象的对应字段将引用同一个对象。
  • 因此,对新对象所做的修改可能会影响到原始对象,因为它们共享相同的引用。

1.2 深拷贝(Deep Copy)

  • 深拷贝创建一个新的对象,并且递归地复制原始对象的所有字段和引用指向的对象,而不仅仅是复制引用本身。
  • 深拷贝会递归复制整个对象结构,包括对象内部的对象,确保新对象和原始对象之间的所有关系都是独立的。
  • 这意味着对新对象所做的修改不会影响到原始对象,因为它们拥有彼此独立的副本。

2. 浅拷贝示例代码

浅拷贝的示例代码如下,我们这里实现了 Cloneable 接口,并重写了 clone() 方法。clone() 方法的实现很简单,直接调用的是父类 Object 的 clone() 方法。

class Address {
    private String city;
    public Address(String city) {
        this.city = city;
    }
    public String getCity() {
        return city;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Person implements Cloneable {
    private Address address;
    public Person(Address address) {
        this.address = address;
    }
    public Address getAddress() {
        return address;
    }
    @Override
    protected Person clone() throws CloneNotSupportedException {
        return (Person) super.clone();
    }
}

在上面的代码中,Address 类实现了 Cloneable 接口,并重写了 clone() 方法,而 Person 类也实现了 Cloneable 接口并重写了 clone() 方法。

在 Address 类的 clone() 方法中,直接调用了父类 Object 的 clone() 方法。

在 Person 类的 clone() 方法中,也直接调用了父类 Object 的 clone() 方法。

接下来我们进行测试,测试代码如下:

public class Main {
    public static void main(String[] args) {
        try {
            Person person1 = new Person(new Address("武汉"));
            Person person1Copy = person1.clone();
            // true
            System.out.println(person1.getAddress() == person1Copy.getAddress());
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

在这个测试中,我们期望输出 true,因为我们实现的是浅拷贝,所以新的 Person 对象和原始的 Person 对象引用的是相同的地址对象。

3. 深拷贝示例代码

这里我们简单对 Person 类的 clone() 方法进行修改,连带着要把 Person 对象内部的 Address 对象一起复制。

class Person implements Cloneable {
    private Address address;
    public Person(Address address) {
        this.address = address;
    }
    public Address getAddress() {
        return address;
    }
    @Override
    protected Person clone() throws CloneNotSupportedException {
        Person person = (Person) super.clone();
        person.address = (Address) this.address.clone();
        return person;
    }
}

在这个修改后的 clone() 方法中,我们首先调用了父类的 clone() 方法创建了一个新的 Person 对象,然后将当前对象的 address 成员变量也进行了克隆,并将克隆后的地址对象赋给新创建的 Person 对象。

接下来,我们来测试一下深拷贝的效果:

public class Main {
    public static void main(String[] args) {
        try {
            Person person1 = new Person(new Address("武汉"));
            Person person1Copy = person1.clone();
            // false
            System.out.println(person1.getAddress() == person1Copy.getAddress());
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

在这个测试中,我们期望输出 false,因为我们实现了深拷贝,所以新的 Person 对象和原始的 Person 对象引用的是不同的地址对象。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号