Java 深浅拷贝

2020-08-25  本文已影响0人  PC_Repair

浅拷贝定义:

深拷贝定义:

"=" 的作用:

浅拷贝

浅拷贝就是直接使用 "=" 给基本类型赋值(即拷贝引用)。

List<String> srcList = new ArrayList<>();
srcList.add("android");
List<String> cpyList = srcList;
srcList.add("ios");
深拷贝

深拷贝就是将所有属性均拷贝到另外一个对象中,将其中任何一个对象任何一个属性发生变化时,另外一个对象不受任何影响。

List<String> srcList = new ArrayList<>();
srcList.add("android");
List<String> cpyList = new ArrayList<>(srcList);
srcList.add("ios");

深拷贝实现

(1)clone 实现深拷贝

每个对象都是继承于 Object 类,Object 类提供了 clone() 方法,通过实现 Cloneable 接口可以使该具有拷贝的能力,拷贝的操作是在内存中进行的,所以性能会比直接构造对象要快速很多

public class DeepCopyByClone {

    public static void main(String[] args) {
        Student s1 = new Student();
        s1.setName("Yao");
        s1.setTeacher(new Teacher("Kobe"));
        Student s2 = s1.clone();
        s2.setName("Yi");
        s2.getTeacher().setName("Jordan");
        System.out.println(s1.getName() + "'s teacher is "
                + s1.getTeacher().getName());
        System.out.println(s2.getName() + "'s teacher is "
                + s2.getTeacher().getName());
    }

}

class Student implements Cloneable {
    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
    protected Student clone() {
        Student student = null;
        try {
            student = (Student) super.clone();
            student.setTeacher(student.getTeacher());
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return student;
    }
}

class Teacher {
    private String name;

    public String getName() {
        return name;
    }

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

    public Teacher(String name) {
        this.name = name;
    }
}
Yao's teacher is Jordan
Yi's teacher is Jordan
image-20200825165912535.png

这里关于teacher的拷贝是通过=号来操作的,仅仅实现了浅拷贝。以下的 clone() 方法的修改将实现深拷贝。

    @Override
    protected Student clone() {
        Student student = null;
        try {
            student = (Student) super.clone();
            //student.setTeacher(student.getTeacher());
            student.setTeacher(new Teacher(student.getTeacher().getName()));
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return student;
    }
Yao's teacher is Kobe
Yi's teacher is Jordan
image-20200825170000030.png

(2)对象序列化实现深拷贝

通过对象序列化,使用 writeObjectreadObject 也可以实现对象的深拷贝。

把对象写到流里的过程是序列化过程Serialization),而把对象从流中读出来的过程则叫做反序列化过程Deserialization)。

应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。

import java.io.*;

public class CloneUtils {

    @SuppressWarnings("unchecked")
    public static Object clone(Object obj) {
        Object cloneObj = null;
        try {
            //写入字节流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream obs = new ObjectOutputStream(out);
            obs.writeObject(obj);
            obs.close();

            //分配内存,写入原始对象,生成新对象
            ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(ios);

            //返回生成的新对象
            cloneObj = ois.readObject();
            ois.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return cloneObj;
    }

    public static void main(String[] args) {
        Student2 s1 = new Student2();
        s1.setName("Yao");
        s1.setTeacher(new Teacher2("Kobe"));
        Student2 s2 = (Student2) CloneUtils.clone(s1);
        s2.setName("Yi");
        s2.getTeacher().setName("Jordan");
        System.out.println(s1.getName() + "'s teacher is "
                + s1.getTeacher().getName());
        System.out.println(s2.getName() + "'s teacher is "
                + s2.getTeacher().getName());
    }
}

class Student2 implements Serializable {
    private String name;
    private Teacher2 teacher;

    public String getName() {
        return name;
    }

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

    public Teacher2 getTeacher() {
        return teacher;
    }

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

class Teacher2 implements Serializable {
    private String name;

    public String getName() {
        return name;
    }

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

    public Teacher2(String name) {
        this.name = name;
    }
}

参考文章:

上一篇 下一篇

猜你喜欢

热点阅读