深拷贝和浅拷贝

拷贝其实就是一个赋值的过程

1、基本类型

深拷贝和浅拷贝的效果是一样的,因为基本类型在赋值的时候,都是直接将值复制一份,而不是复制引用。

基本类型包括:byte, short, int, long, float, double, char, boolean。

基本类型的变量所对应的内存区域存储的是值,当我们对基本类型进行复制的时候,实际上是创建了一个新的变量,并把原变量的值复制过去。后续对新变量的修改并不会影响到原变量。

例如:

int a = 1;

int b = a;

b = 2;

System.out.println(a); // 输出 1

System.out.println(b); // 输出 2

例子中,ab 是基本类型的变量,我们将 a 的值赋给 b,然后修改 b 的值,但这并不会影响到 a 的值。

所以,对于基本类型来说,无论是深拷贝还是浅拷贝,结果都是一样的,因为都是直接复制值。

2、引用类型

        2.1 基本概念

                浅拷贝只复制对象本身,而不复制对象包含的引用。这意味着复制后的对象与原对象共享引用类型的成员变量。因此,如果这些成员变量的值发生改变,那么复制的对象和原对象都会受到影响。

        深拷贝不仅复制对象本身,还会复制对象包含的引用。这就意味着复制后的对象与原对象不共享引用类型的成员变量。所以,即使这些成员变量的值发生改变,复制的对象和原对象也是互不影响的。

        2.2代码解释

                假设我们有一个类Person,它有一个成员变量Address(这是一个引用类型):

        class Address { String city; }

        class Person { Address address; }

                浅拷贝时,只会复制Person对象本身,也就是说,会创建一个新的Person对象,并且这个新对象的address字段与原对象的address字段指向同一个Address对象。这就意味着,如果我们改变了原对象的address字段的city属性,那么新对象的address字段的city属性也会跟着改变。

        而深拷贝则不同,它会复制Person对象本身,同时也会复制Person对象包含的引用,也就是说,会创建一个新的Person对象,这个新对象的address字段会指向一个新的Address对象,这个新的Address对象的city属性与原对象的address字段的city属性相同,但是它们并不是同一个对象。所以,即使我们改变了原对象的address字段的city属性,新对象的address字段的city属性也不会发生改变。(可以理解为深拷贝 新对象 新引用

        2.3代码展示

class Address implements Cloneable {
    String street;
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

class Person implements Cloneable {
    String name;
    Address address;
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public static void main(String[] args) throws CloneNotSupportedException {
    Address addr = new Address();
    addr.street = "Nanjing Road";
    Person p1 = new Person();
    p1.name = "Tom";
    p1.address = addr;
    Person p2 = (Person) p1.clone();
    System.out.println(p1.address.street);  // 输出:Nanjing Road
    System.out.println(p2.address.street);  // 输出:Nanjing Road
    p2.address.street = "Chang'an Road";
    System.out.println(p1.address.street);  // 输出:Chang'an Road
    System.out.println(p2.address.street);  // 输出:Chang'an Road
}

浅拷贝:p1和p2的address字段指向同一个对象,所以修改p2的address字段也会影响p1

 

class Address implements Cloneable {
    String street;
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

class Person implements Cloneable {
    String name;
    Address address;
    public Object clone() throws CloneNotSupportedException {
        //调用父类(Object类)的clone()方法来复制当前对象,然后把复制的对象转型为Person类型,并赋值给cloned变量。
        Person cloned = (Person) super.clone();
        //调用address对象的clone()方法来复制address对象,然后把复制的对象转型为Address类型,并赋值给cloned的address属性。
        cloned.address = (Address) address.clone();
        return cloned;
    }
}

public static void main(String[] args) throws CloneNotSupportedException {
    Address addr = new Address();
    addr.street = "Nanjing Road";
    Person p1 = new Person();
    p1.name = "Tom";
    p1.address = addr;
    Person p2 = (Person) p1.clone();
    System.out.println(p1.address.street);  // 输出:Nanjing Road
    System.out.println(p2.address.street);  // 输出:Nanjing Road
    p2.address.street = "Chang'an Road";
    System.out.println(p1.address.street);  // 输出:Nanjing Road
    System.out.println(p2.address.street);  // 输出:Chang'an Road
}
深拷贝:我们在Person的clone方法中,不仅克隆了Person对象,也克隆了其引用的Address对象。所以修改p2的address字段不会影响p1。

3.必须掌握基本概念

        3.1类与对象的关系
             在面向对象编程中,类(Class)是一种抽象的模板,用于描述具有相同属性(字段)和方法的对象的集合。而实例(Instance)则是根据这个模板创建出来的具体的对象。 比如,我们可以创建一个名为"Animal"的类,这个类可能有"name"、"age"等属性,和"eat"、"sleep"等方法。这个"Animal"类就像是一个模板,定义了一种动物应该具有的基本特征和行为。但是,类本身并不能代表具体的动物,我们无法通过"Animal"类直接知道这个动物的名字是什么,或者它现在在做什么。 所以,我们需要创建一个"Animal"类的实例,比如一个名字为"Tom"的猫,这个猫就是"Animal"类的一个实例。通过这个实例,我们可以知道这个动物的名字是"Tom",并且可以让它执行"eat"、"sleep"等操作。 "类的实例"这个名称的出现,是因为在面向对象编程中,我们需要一种方式来表示根据类模板创建出来的具体的对象,所以就有了"实例"这个概念

        3.2在编程中,当我们说一个字段指向一个对象,我们是指该字段在内存中存储的是这个对象的地址。

在Java中,对象是通过引用来操作的。当我们创建一个对象时,如Address a1 = new Address();,实际上有两件事发生:一是在内存中为新的Address对象分配空间,二是将这个新对象的内存地址赋值给变量a1。这样,a1就指向了新创建的Address对象。

        3.3对象本身:

        对象的实力, 包含类定义的属性和方法

        3.4.对象包含的引用:

        如果对象的字段是引用类型, 那么这些字段就是对象包含的引用,是一个引用类型,指向一个对象。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值