浅拷贝和深拷贝

        对象创建完之后是放在堆里面的,每一个线程有一个栈(比如启动一个main函数这就是一个主线程,每个线程都有自己的栈),栈里面存在的是对这个对象的引用。很多时候 = null其实意思就是说他的引用为空,就是没有指向任何东西。

浅拷贝:

        创建一个A对象和一个B对象,如果简简单单的 A=B 其实就是将B对堆里面某个对象的引用复制给了A,你对A引用的对象进行修改,你会发现B引用的对象也被修改了,这就说明他们两个引用的是同一个对象,这就是浅拷贝(只拷贝引用)。

        比如下面这个例子,我这个对象的属性之后,所有的都跟着变了。(所以有时候赋值的时候要注意,别把所有的都改掉了)

 @Test
    public void test() {
        TestOneDao testOne = new TestOneDao();
        testOne.id = 1;
        testOne.name = "张三";
        TestOneDao testTwo = testOne;
        //==是直接比较的地址
        System.out.println(testOne == testTwo);
        //***************
        //如果修改testOne的数据testTwo也变了
        testOne.name = "李四";
        System.out.println(testTwo);
        //****************
    }

可以看到使用==比较两个对象的地址发现是一样的,同时修改testOne之后testTwo也变了

 

 深拷贝:

        先看下JDK原生注释

        Object类中提供了一个方法:clone() 在看一下他的文档解释

        父类提供的这个方法是用protected修饰的,所以需要重写这个方法,同时把修饰符改成public,然后再看文档中的介绍,需要实现Cloneable接口才可以使用这个方法,否则会抛出异常

类实现

//首先我们需要继承Cloneable接口
public class TestOneDao implements Cloneable{

//接下来我们需要重写方法,同时把修饰符改成public
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

 现在用代码来测试一下:

        ,但是修改其中一个对象后,另外一个对象并没有改变,这就等于调用clone()方法之后在堆中创建出了一个一模一样的对象,这就是深拷贝

 @Test
    public void test() {
        TestOneDao testOne = new TestOneDao(1,"张三");
        TestOneDao testTwo = new TestOneDao();
        try {
            testTwo = (TestOneDao) testOne.clone();
            //必须使用try/Catch环绕抛出CloneNotSupportedException异常
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        System.out.println("*******输出对象*******");
        System.out.println("testOne: "+testOne);
        System.out.println("testTwo: "+testTwo);
        System.out.println("*******输出对象*******");
        System.out.println("*******地址比较*******");
        System.out.println(testOne == testTwo);
        System.out.println("*******地址比较*******");
        System.out.println("*******赋值测试*******");
        testOne.name = "李四";
        System.out.println(testTwo);
        System.out.println("*******赋值测试*******");
        System.out.println("*******比较Hash值*******");
        System.out.println(testOne.hashCode());
        System.out.println(testTwo.hashCode());
        System.out.println("*******比较Hash值*******");
    }


 补充几点:

关于深拷贝的话还有很多种方式,比如需要注意的是反序列化的时候就会重新生成对象,然后spring,Json的一些方法都可以,但是肯定原生的clone是最快的,可以看到他的修饰字段 native

 这个意思就是有计算机底层实现的方法。所以不要想着花里胡哨,不要重复造轮子

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值