Java的深克隆与浅克隆

浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。

深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。

总之深浅克隆都会在堆中新分配一块区域,区别在于对象属性引用的对象是否需要进行克隆(递归性的)。

1、浅克隆

public class Student implements Cloneable{
    private String name;
    private Integer age;
    private Teacher teacher;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Teacher getTeacher() {
        return teacher;
    }

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

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Teacher implements Cloneable{

    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

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

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

 public static void main(String[] args) throws Exception{
        Teacher teacher = new Teacher();
        teacher.setName("张老师");
        teacher.setAge(42);
        Student student = new Student();
        student.setName("李晓明");
        student.setAge(15);
        student.setTeacher(teacher);
        System.out.println(student);

        Student student2 = (Student) student.clone();
        student2.setAge(18);
        teacher.setAge(50);
        System.out.println(student);
        System.out.println(student2);
    }
浅克隆.png

student2克隆student后teacher都指向同一内存地址,修改student的teacher对象,student中teacher也随之改变

2、手动实现深克隆

对象类都需要实现Cloneable接口

public class Student implements Cloneable{
    private String name;
    private Integer age;
    private Teacher teacher;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Teacher getTeacher() {
        return teacher;
    }

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

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

    @Override
    protected Object clone() throws CloneNotSupportedException {

        Student student = (Student) super.clone();
        //手动克隆teacher
        student.setTeacher((Teacher) student.getTeacher().clone());
        return student;
    }
}
public class Teacher implements Cloneable{

    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
 public static void main(String[] args) throws Exception{
        Teacher teacher = new Teacher();
        teacher.setName("张老师");
        teacher.setAge(42);
        Student student = new Student();
        student.setName("李晓明");
        student.setAge(15);
        student.setTeacher(teacher);
        System.out.println(student);

        Student student2 = (Student) student.clone();
        student2.setAge(18);
        teacher.setAge(50);
        System.out.println(student);
        System.out.println(student2);
    }
手动实现深克隆.png

student2的teacher并不会随之改变

3、序列化实现深克隆

public class Student implements Serializable{
    private static final long serialVersionUID = -5763470826096290328L;
    private String name;
    private Integer age;
    private Teacher teacher;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Teacher getTeacher() {
        return teacher;
    }

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

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

    public Object deepCopy()throws Exception
    {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
        //将当前这个对象写到一个输出流当中,因为这个对象的类实现了Serializable这个接口,
        // 所以在这个类中,有一个引用,这个引用如果实现了序列化,那么这个也会写到这个输出流当中
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();
        //这个就是将流中的东西读出类,读到一个对象流当中,这样就可以返回这两个对象的东西,实现深克隆
    }
}
public class Teacher implements Serializable{
    private static final long serialVersionUID = 4018726304594413514L;
    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

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

}

public static void main(String[] args) throws Exception{
        Teacher teacher = new Teacher();
        teacher.setName("张老师");
        teacher.setAge(42);
        Student student = new Student();
        student.setName("李晓明");
        student.setAge(15);
        student.setTeacher(teacher);
        System.out.println(student);

        Student student2 = (Student) student.deepCopy();
        student2.setAge(18);
        teacher.setAge(50);
        System.out.println(student);
        System.out.println(student2);
    }
序列化实现深克隆.png

执行结果同上面一致

你可能感兴趣的:(Java的深克隆与浅克隆)