浅克隆和深克隆

59 阅读2分钟

结论:浅克隆中克隆对象和被克隆对象的内部对其他对象的引用都指向同一个对象。
深克隆中克隆对象和被克隆对象的内部对其他对象的引用指向不同的对象。
也就是说,浅克隆对对象的内部引用只复制地址值而不会去克隆指向的对象,但深克隆会去克隆。

实现

浅克隆

测试类:

//老师类
public class Teacher {
    private Integer pkid;
    private  String name;

    public Teacher(Integer pkid, String name) {
        this.pkid = pkid;
        this.name = name;
    }
//略过get、set方法
.......
}
public class Student implements Cloneable{
    private double weight;
    private Integer pkid;
    private String name;
    //教师类的引用对象
    private Teacher teacher;

    public Student(double weight, Integer pkid, String name, Teacher teacher) {
        this.weight = weight;
        this.pkid = pkid;
        this.name = name;
        this.teacher = teacher;
    }

    @Override
    protected Object clone(){
        Object object = null;
        try {
            object = super.clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
        return object;
    }

    @Override
    public String toString(){
        return "studnet " + "weight =" +weight + "pkid =" + pkid + "teacher =" +teacher;
    }


    //省略get、set方法
    ........
}

测试用例

public class clonetest1 {
    public static void main(String[] args) {
         Teacher teacher1 = new Teacher(1,"黄");
         Student student1 = new Student(50.0D,1,"张三",teacher1);

         Student student2 = (Student) student1.clone();

        System.out.println(student1 == student2);
        System.out.println(student1.getTeacher());
        System.out.println(student2.getTeacher());

        System.out.println(student1.getTeacher() == student2.getTeacher());
        //hashcode比较
        System.out.println(student1.getTeacher().hashCode());
        System.out.println(student2.getTeacher().hashCode());
    }
}

false
clonetest.Teacher@6ed3ef1
clonetest.Teacher@6ed3ef1
true
116211441
116211441

从结果中看到:两个学生对象不是同一个对象,两个学生类的内部对象 老师对象,是同一个对象。

深克隆

深克隆的实现可以通过克隆的循环嵌套实现,也可以通过序列化来实现。

克隆循环嵌套:

public class Teacher implements Cloneable {
    private Integer pkid;
    private  String name;

    public Teacher(Integer pkid, String name) {
        this.pkid = pkid;
        this.name = name;
    }

    @Override
    protected Object clone(){
        Object object = null;
        try {
            object = super.clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
        return object;
    }
    //省略getset方法
    }
public class Student implements Cloneable{
    private double weight;
    private Integer pkid;
    private String name;
    //教师类的引用对象
    private Teacher teacher;

    public Student(double weight, Integer pkid, String name, Teacher teacher) {
        this.weight = weight;
        this.pkid = pkid;
        this.name = name;
        this.teacher = teacher;
    }
    //克隆方法内部调用了teacher类的克隆方法
    @Override
    protected Object clone(){
       Student student = null;
        try {
            student = (Student) super.clone();
            student.teacher = (Teacher) this.teacher.clone();
        }catch (CloneNotSupportedException e){
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
        return student;
    }

    @Override
    public String toString(){
        return "studnet " + "weight =" +weight + "pkid =" + pkid + "teacher =" +teacher;
    }
    //省略getset方法
    }

同样的测试用例,结果就有所不同

false
clonetest.Teacher@1b6d3586
clonetest.Teacher@4554617c
false
460141958
1163157884

序列化方法就是将对象序列化再反序列化实现克隆。