深拷贝、浅拷贝、引用拷贝

跟着小欢子把深拷贝、浅拷贝、引用拷贝彻底分清楚吧!

首先介绍一下我们会使用到的两个类Demo1,Demo2(为了方便我们实验,就不进行封装处理啦)。

public class Demo1 {

    String name;

    int age;

    @Override
    public String toString() {
        return "Demo1{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Demo2 {

    String name;

    int age;

    Demo1 demo;

    @Override
    public String toString() {
        return "Demo2{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", demo=" + demo +
                '}';
    }
}

引用拷贝

引用拷贝就是我们最常用直接赋值啦,直接上代码!

实验1

public static void main(String[] args) {

        Demo1 demo1=new Demo1();
        demo1.name="xiaohuanzi";
        demo1.age=25;
        Demo1 tempDemo=demo1;
        tempDemo.name="yuanyuan";
        tempDemo.age=18;
        System.out.println(tempDemo);
        System.out.println(demo1);
    }

实验1运行结果

Demo1{name='yuanyuan', age=18}
Demo1{name='yuanyuan', age=18}

通过运行实验1运行结果可知,当我们进行引用拷贝时,拷贝是对象的地址,即tempDemo指向的也是demo1,所以当我们修改tempDemo时,其实修改的是tempDemo指向的对象,因此demo1也会跟着变化。

浅拷贝

谈到浅拷贝,就需要我们继承接口Cloneable,并重写clone方法啦,我们对Demo1,Demo2稍作修改。

public class Demo1 implements Cloneable{

    String name;

    int age;

    @Override
    public String toString() {
        return "Demo1{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public class Demo2 implements Cloneable{

    String name;

    int age;

    Demo1 demo;

    @Override
    public String toString() {
        return "Demo2{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", demo=" + demo +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

实验2

public static void main(String[] args) {

        Demo2 demo2=new Demo2();
        demo2.name="xiaohuanzi";
        demo2.age=25;
        Demo1 demo1=new Demo1();
        demo1.name="congcong";
        demo1.age=25;
        demo2.demo=demo1;
        try {
            Demo2 tempDemo=(Demo2)demo2.clone();
            tempDemo.name="yuanyuan";
            tempDemo.age=18;
            tempDemo.demo.name="404";
            tempDemo.demo.age=18;
            System.out.println(demo2);
            System.out.println(tempDemo);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }

试验2的运行结果

Demo2{name='xiaohuanzi', age=25, demo=Demo1{name='404', age=18}}
Demo2{name='yuanyuan', age=18, demo=Demo1{name='404', age=18}}

从实验2的运行结果可以看到,当我们通过clone方法进行拷贝后,修改拷贝对象tempDemo的基本数据类型name,age并不会影响原对象,但是修改引用类型成员demo仍然会影响原对象。因此我们可以得出一个结论,浅拷贝确实是重新创建了一个实例,但是实例内部的引用类型成员依旧是引用拷贝。

深拷贝

深拷贝的实现需要我们在Demo2重写的clone方法里面再次进行修改,如下:

@Override
    protected Object clone() throws CloneNotSupportedException {

        Demo2 demo2=(Demo2)super.clone();
        demo2.demo=(Demo1) demo2.demo.clone();
        return demo2;
    }

实验3

public static void main(String[] args) {

        Demo2 demo2=new Demo2();
        demo2.name="xiaohuanzi";
        demo2.age=25;
        Demo1 demo1=new Demo1();
        demo1.name="congcong";
        demo1.age=25;
        demo2.demo=demo1;
        try {
            Demo2 tempDemo=(Demo2)demo2.clone();
            tempDemo.name="yuanyuan";
            tempDemo.age=18;
            tempDemo.demo.name="404";
            tempDemo.demo.age=18;
            System.out.println(demo2);
            System.out.println(tempDemo);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }

实验3的运行结果

Demo2{name='xiaohuanzi', age=25, demo=Demo1{name='congcong', age=25}}
Demo2{name='yuanyuan', age=18, demo=Demo1{name='404', age=18}}

通过实验3的运行结果我们可以得知,通过深拷贝后,修改拷贝对象tempDemo并不会影响原对象,包括基本数据类型成员以及引用类型成员。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值