简单引用、浅拷贝与深拷贝

原文链接:https://blog.csdn.net/zhangjg_blog/article/details/18369201/
简单引用
new操作符的本意是分配内存。程序执行到new操作符时, 首先去看new操作符后面的类型,因为知道了类型,才能知道要分配多大的内存空间。分配完内存之后,再调用构造函数,填充对象的各个域,这一步叫做对象的初始化,构造方法返回后,一个对象创建完毕,可以把他的引用(地址)发布到外部,在外部就可以使用这个引用操纵这个对象。
结构图如下:
  在这里插入图片描述

public class demo1Clone {
   public static void main(String[] args) {
       System.out.println("复制初始化");
       Person p = new Person(1001,"初始",true);
       System.out.println(p);
       Person p1 = p;
       System.out.println(p1);
       System.out.println("修改p后");
       p.setId(1002);
       p.setName("修改");
       System.out.println(p);
       System.out.println(p1);
   }
}

输出结果:
在这里插入图片描述

浅拷贝

被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换而言之,浅拷贝可以拷贝这个对象的变量,但是不能拷贝这个对象所引用的对象。可以通过clone()方法进行浅拷贝。
  通过建立一个Depart类,如果想要对这个类的对象能够进行浅复制,需要进行两部操作:一是引入Cloneable接口,二是重写clone()方法。
  代码如下所示:

public class demo1Clone {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person p = new Person(1001,"职工姓名",true);
        System.out.println(p);
        Depart depart = new Depart(p,"IT部");

        Depart depart1 = (Depart) depart.clone();
        System.out.println(depart1.person);
        System.out.println("depart地址:"+depart);
        System.out.println("depart1地址:"+depart1);
        System.out.println("person地址:"+p);
        System.out.println("depart的person地址:"+depart.person);
        System.out.println("depart1的person地址:"+depart1.person);
    }
    static class Depart implements Cloneable{
        private Person person;
        private String name;

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

        public Depart(Person person, String name) {
            this.person = person;
            this.name = name;
        }

        public Person getPerson() {
            return person;
        }

        public void setPerson(Person person) {
            this.person = person;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

在这里插入图片描述
通过对上面代码进行分析:depart与他的复制体depart1不是同一个地址,但是他们的引用对象person却是同一个地址。
再具体一下进行修改,将如下代码加入main函数。

        depart.setName("销售部");
        System.out.println("depart的名字:"+depart.getName());
        System.out.println("depart1的名字:"+depart1.getName());
        p.setName("刘晓燕");
        System.out.println("depart中person的职工姓名:"+depart.person.getName());
        System.out.println("depart1中person的职工姓名:"+depart1.person.getName());

得出输出结果:
在这里插入图片描述
由结果可知对于Depart中由于引用了Cloneable接口,所以是可以对一些变量进行拷贝的,但是对于Depart对象中引用对象是无法进行拷贝的,他们引用的是同一个地址的对象。
这个时候就可以考虑对于Person进一步与原对象的隔离,也就是深拷贝。

深复制

被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
  因此我们对上面的例子进一步操作,我们需要得到的是割裂person对于depart与他的复制对象depart1的联系,具体操作分三步:
  1,Person对象引入Cloneable接口;
  2,重写Person类中clone()方法;
  3,在引用Person类的Depart中的clone()方法中引入新的person类。
  具体代码如下所示:

public class demo1Clone {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person p = new Person(1001,"罗宾汉",true);
        System.out.println(p);
        Depart depart = new Depart(p,"IT部");

        Depart depart1 = (Depart) depart.clone();
        System.out.println(depart1.person);
        System.out.println("depart地址:"+depart);
        System.out.println("depart1地址:"+depart1);
        System.out.println("person地址:"+p);
        System.out.println("depart的person地址:"+depart.person);
        System.out.println("depart1的person地址:"+depart1.person);
        depart.setName("销售部");
        System.out.println("depart的名字:"+depart.getName());
        System.out.println("depart1的名字:"+depart1.getName());
        p.setName("刘晓燕");
        System.out.println("depart中person的职工姓名:"+depart.person.getName());
        System.out.println("depart1中person的职工姓名:"+depart1.person.getName());
    }
    static class Depart implements Cloneable{
        private Person person;
        private String name;

        @Override
        protected Object clone() throws CloneNotSupportedException {
            Depart depart = (Depart) super.clone();
            depart.person = (Person) person.clone();
            return depart;
        }

        public Depart(Person person, String name) {
            this.person = person;
            this.name = name;
        }

        public Person getPerson() {
            return person;
        }

        public void setPerson(Person person) {
            this.person = person;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

结果如下:
在这里插入图片描述
我们只看最后的输出结果,很明显,depart与depart1中的person对象不再相同,这时候两个对象在他们的引用对象上发生了割裂。
但是,需要注意的是原对象的person是跟person的没有割裂的,这两个指向同一个地址。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值