[java]深拷贝和浅拷贝的区别介绍

为什么要使用Clone?深拷贝和浅拷贝的区别有哪些?

1.首先明白什么是引用?

​ 当我们在创建对象时,首先在堆区进行内存的分配,然后调用构造方法进行初始化。对象的实例保存在堆中,对象的引用保存在栈中。引用就好像c语言中的指针一样保存着对象实例的地址,我们实际通过操作对象的引用来操作对象。

在这里插入图片描述

2. clone帮助我们解决了什么问题?为什么要进行clone?

    class Person{
        String name;
        int age;
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
        public String getName() {
            return name;
        }
        public int getAge() {
            return age;
        }
    }
    public class Test3 {
        public static void main(String[] args) {
            Person p1 = new Person("xiaowang",12);
            System.out.println(p1.getAge()+p1.getName());
            Person p2 = p1;
            p2.age = 13;
            System.out.println(p1.getAge()+p1.getName());
        }
    }

现有一个Person类,类的成员变量有name,age

首先new 一个 Person p1对象,通过有参构造方法赋值它的name=“xiaowang",age = 12

把p1对象赋值给p2对象。我们修改p2对象的age时,奇怪的现象发生了。控制台输出了

    12xiaowang
    13xiaowang

此时p1对象的age也发生了改变

为什么?因为通过 == 赋值其实是赋值的是对象引用,此时p1,p2都指向了同一块内存空间,对其中一个的修改都会影响所有的指向该内存空间引用的对象。clone就是帮助我们解决这种引用赋值问题的

​ 3 .什么是深clone?什么是浅clone?

​ 由于 age 是基本数据类型, 那么对它的拷贝没有什么疑议,直接将一个 4 字节的整数值拷贝过来就行。但是 name是 String 类型的, 它只是一个引用, 指向一个真正的 String 对象,那么对它的拷贝有两种方式: 直接将原对象中的 name 的引用值拷贝给新对象的 name 字段, 或者是根据原 Person 对象中的 name 指向的字符串对象创建一个新的相同的字符串对象,将这个新字符串对象的引用赋给新拷贝的 Person 对象的 name 字段。这两种拷贝方式分别叫做浅拷贝和深拷贝。深拷贝和浅拷贝的原理如下图所示:

在这里插入图片描述
下面通过代码进行验证。如果两个 Person 对象的 name 的地址值相同, 说明两个对象的 name 都指向同一个
String 对象,也就是浅拷贝, 而如果两个对象的 name 的地址值不同, 那么就说明指向不同的 String 对象, 也就是在拷贝 Person 对象的时候, 同时拷贝了 name 引用的 String 对象, 也就是深拷贝。验证代码如下:

我们来到程序测试一下 clone的person对象是深拷贝,还是浅拷贝?

Person p1 = new Person("xiaowang",12);
Person p2 = (Person) p1.clone();
System.out.println(p1.getName()==p2.getName());

output 
--
true

输出为true ,说明name指向的是同一块内存空间,这种拷贝方式是浅拷贝。

4.如何进行深拷贝:
由上一节的内容可以得出如下结论:如果想要深拷贝一个对象,这个对象必须要实现 Cloneable 接口,实现 clone
方法,并且在 clone 方法内部,把该对象引用的其他对象也要 clone 一份,这就要求这个被引用的对象必须也要实现Cloneable 接口并且实现 clone 方法。那么,按照上面的结论,实现以下代码 Body 类组合了 Head 类,要想深拷贝Body 类,必须在 Body 类的 clone 方法中将 Head 类也要拷贝一份。代码如下:

 class Body implements Cloneable{
    public Head head;
    public Body() {}
    public Body(Head head) {this.head = head;}
    @Override
    protected Object clone() throws CloneNotSupportedException {
    Body newBody = (Body) super.clone();
    newBody.head = (Head) head.clone(); return newBody;
   }
     }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值