Java对象拷贝

2019-02-20  本文已影响0人  Charein

常用的对象拷贝有2种方式,分别是浅拷贝深拷贝

1. 浅拷贝

在浅拷贝中,如果原型对象的成员变量是值类型,将复制一份给拷贝对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给拷贝对象,也就是说原型对象和拷贝对象的成员变量指向相同的内存地址。

看如下例子

public class ClassRoom implements Cloneable {
    public String name;
    public int studentNum;
    public Student student;

    public ClassRoom(String name, int studentNum, Student student) {
        this.name = name;
        this.studentNum = studentNum;
        this.student = student;
    }

    @Override
    public String toString() {
        return "ClassRoom{" +
                "name='" + name + '\'' +
                ", studentNum=" + studentNum +
                ", student=" + student +
                '}';
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Student implements Cloneable {
    public String name;
    public int age;
    public boolean isBoy;

    public Student(String name, int age, boolean isBoy) {
        this.name = name;
        this.age = age;
        this.isBoy = isBoy;
    }

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

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

拷贝Student对象测试

    public static void main(String[] args) {
        Student student = new Student("cyy", 20, true);
        System.out.println("student: " + student);

        Student studentNew;
        try {
            studentNew = (Student) student.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return;
        }
        student.name = "yt";
        student.age = 10;
        student.isBoy = false;

        System.out.println("studentNew: " + studentNew);

        // 输出
        // student: Student{name='cyy', age=20, isBoy=true}
        // studentNew: Student{name='cyy', age=20, isBoy=true}
    }

从打印结果可以发现student对象里面的name,age,isBoy全部被拷贝到studentNew对象。

如果对象里面又嵌套一个对象的情况

    public static void main(String[] args) {
        Student student = new Student("cyy", 20, true);
        ClassRoom classRoom = new ClassRoom("一年级", 100, student);
        System.out.println("classRoom: " + classRoom);

        ClassRoom classRoomNew;
        try {
            classRoomNew = (ClassRoom) classRoom.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return;
        }

        classRoom.name = "二年级";
        classRoom.studentNum = 200;
        classRoom.student.age = 10;
        classRoom.student.name = "yt";
        classRoom.student.isBoy = false;

        System.out.println("classRoomNew: " + classRoomNew);

        // 输出
        // classRoom: ClassRoom{name='一年级', studentNum=100, student=Student{name='cyy', age=20, isBoy=true}}
        // classRoomNew: ClassRoom{name='一年级', studentNum=100, student=Student{name='yt', age=10, isBoy=false}}
    }

从打印结果可以发现classroom的name,studentNum内容被拷贝classroomNew对象,而student对象没有被拷贝过来(这时就需要使用深拷贝)。

2.深拷贝

在深拷贝中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给拷贝对象,深拷贝将原型对象的所有引用对象也复制一份给拷贝对象。

看如下例子

public class ClassRoom implements Cloneable {
    public String name;
    public int studentNum;
    public Student student;

    public ClassRoom(String name, int studentNum, Student student) {
        this.name = name;
        this.studentNum = studentNum;
        this.student = student;
    }

    @Override
    public String toString() {
        return "ClassRoom{" +
                "name='" + name + '\'' +
                ", studentNum=" + studentNum +
                ", student=" + student +
                '}';
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        ClassRoom classRoom = (ClassRoom) super.clone();
        classRoom.student = (Student) student.clone();
        return classRoom;
    }
}
public class Student implements Cloneable {
    public String name;
    public int age;
    public boolean isBoy;

    public Student(String name, int age, boolean isBoy) {
        this.name = name;
        this.age = age;
        this.isBoy = isBoy;
    }

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

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
  public static void main(String[] args) {
        Student student = new Student("cyy", 20, true);
        ClassRoom classRoom = new ClassRoom("一年级", 100, student);
        System.out.println("classRoom: " + classRoom);

        ClassRoom classRoomNew;
        try {
            classRoomNew = (ClassRoom) classRoom.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            return;
        }

        classRoom.name = "二年级";
        classRoom.studentNum = 200;
        classRoom.student.age = 10;
        classRoom.student.name = "yt";
        classRoom.student.isBoy = false;

        System.out.println("classRoomNew: " + classRoomNew);

        // 输出
        // classRoom: ClassRoom{name='一年级', studentNum=100, student=Student{name='cyy', age=20, isBoy=true}}
        // classRoomNew: ClassRoom{name='一年级', studentNum=100, student=Student{name='cyy', age=20, isBoy=true}}
    }

从打印结果可以发现classRoom对象的name,studentNum和student对象内容全部被拷贝到classRoomNew对象。

注:浅拷贝/深拷贝需要实现Cloneable接口,并覆盖clone方法,而且clone方法必须是public访问。

参考 https://blog.csdn.net/ztchun/article/details/79110096

上一篇下一篇

猜你喜欢

热点阅读