java 深浅拷贝解析和实现实例

1、引用拷贝:拷贝的是引用,但是源和复制都指向同一个对象

2、浅拷贝:源和复制的所有变量值都相同,但是仅仅拷贝的是源对象,源对象里的引用所指向的对象并没有被拷贝。

3、深拷贝:深拷贝会拷贝源对象的所有属性,并拷贝属性指向的动态分配的内存,也就是说拷贝源对象以及源对象里引用所指向的对象。

 

示例代码:

1、教师类:

package clone;

import java.io.Serializable;

public class Teacher implements Cloneable,Serializable {
    private String name;

    public String getName() {
        return name;
    }

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

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

2、学生类:

package clone;

import java.io.*;

public class Student implements Cloneable,Serializable {
    private String name;
    private Teacher teacher;

    public String getName() {
        return name;
    }

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

    public Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

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

    public Student deepClone1() throws CloneNotSupportedException {
        Student student = (Student) super.clone();
        Student s3 = student;
        s3.setTeacher((Teacher) student.getTeacher().clone());
        return s3;
    }

    public Object deepClone2() throws Exception {
        // 序列化
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);

        // 反序列化
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();
    }
}

3、测试类:

package clone;

public class TestClone {
    public static void main(String[] args) throws Exception {
        //引用拷贝
        Teacher t1 = new Teacher();
        t1.setName("张老师");
        Student s1 = new Student();
        s1.setName("李同学");
        s1.setTeacher(t1);
        Student s2 = s1;
        System.out.println("*****************引用拷贝*********************");
        System.out.println(s1);
        System.out.println(s2);
        System.out.println("*****************引用拷贝*********************\n");

        //浅拷贝
        Student s3 = (Student) s1.clone();
        System.out.println("*****************浅拷贝*********************");
        System.out.println(s1);
        System.out.println(s3);
        System.out.println(s1.getTeacher());
        System.out.println(s3.getTeacher());
        System.out.println("*****************浅拷贝*********************\n");

        //深拷贝1
        Student s4 = s1.deepClone1();
        System.out.println("*****************深拷贝1*********************");
        System.out.println(s1);
        System.out.println(s4);
        System.out.println(s1.getTeacher());
        System.out.println(s4.getTeacher());
        System.out.println("*****************深拷贝1*********************\n");

        //深拷贝2
        Student s5 = (Student)s1.deepClone2();
        System.out.println("*****************深拷贝2*********************");
        System.out.println(s1);
        System.out.println(s5);
        System.out.println(s1.getTeacher());
        System.out.println(s5.getTeacher());
        System.out.println("*****************深拷贝2*********************\n");
    }
}

4、运行结果:

5、结果分析:

     1)、引用拷贝中,源对象和复制对象的引用指向的是同一个对象,所以打印出来的地址也相同

     2)、浅拷贝中,可通过 Cloneable 类的 clone() 方法进行浅拷贝。从打印出来的日志看,源对象和复制对应的引用地址是不一样的,但是对象里面的教师对象的引用地址是一样的,这是不彻底的拷贝

     3)、深拷贝中,有两种实现方式:

              a、重写 Cloneable.clone() 方法,克隆源对象的同时,把里面的对象也克隆。

              b、重写 Cloneable.clone() 方法,利用序列化进行深拷贝,把源对象写入一个字节流中,然后再将其读出,则可创建一个新的对象,并且该新对象与源对象之间并不存在引用共享的问题,真正实现对象的深拷贝。

            从打印的日志来看,深拷贝1和深拷贝2的源对象和复制对象、源对象里的对象和复制对象里的对象引用地址均不相同,说明实现了深拷贝。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值