深入理解Java浅拷贝和深拷贝

首先说一下什么是引用拷贝和对象拷贝。

1. 引用拷贝:

​ 引用拷贝就是创建一个指向对象的引用变量的拷贝,拷贝后生成的对象和原来的对象仍是一个对象,也就是说他们在内存空间中的地址是一样的。

2. 对象拷贝

​ 对象拷贝就是创建对象本身的一个副本,就是在内存空间中开辟一个新的区域存放该对象,这时候就是两个对象了!

深拷贝和浅拷贝都是对象拷贝

1.浅拷贝

​ 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享。

简单来说就是只拷贝你考虑的对象,对于内部对象和原来的对象共享。

下面结合代码来看看:

//教师类,是学生类的内部对象
//实现Cloneable接口,默认实现的是浅拷贝
public class Teacher implements Cloneable {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

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

//学生类,也是我们要拷贝的“主类”
public class Student implements Cloneable {
    private String name;
    private int age;
    private Teacher teacher;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Teacher getTeacher() {
        return teacher;
    }

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

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

测试类:

public class shallowCopy {
    public static void main(String[] args) throws CloneNotSupportedException {
        Teacher teacher = new Teacher();
        teacher.setName("liumei");
        teacher.setAge(25);

        Student student1 = new Student();
        student1.setName("mike");
        student1.setAge(18);
        student1.setTeacher(teacher);

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

        //student
        System.out.println(student1);
        System.out.println(student2);
        
        //teacher
        System.out.println(student1.getTeacher());
        System.out.println(student2.getTeacher());

    }
}

测试结果:

从结果中可以看出,student1和student2是两个对象,而两个学生对象的teacher对象地址却是相同的,这也就印证了我们上边的结论,浅拷贝是不拷贝内部引用的对象的!

2. 深拷贝

​ 深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。

简而言之,深拷贝把要复制的对象和引用的对象都复制了一遍。

下面结合代码来看看:

教师类和上述代码一致,我们只看学生类。

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Teacher getTeacher() {
        return teacher;
    }

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

 

    /**
     * 深拷贝:不仅赋值主对象,还将内部的对象也重新复制一份
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        //拷贝student对象
        Student student = (Student) super.clone();
        //拷贝teacher对象,并将其放入拷贝后生成的student对象中
        student.setTeacher((Teacher) teacher.clone());
        return student;
    }
}

测试类与浅拷贝一致,我们直接看结果:

诶? 这次不仅两个学生类的地址不一样了,连内部的teacher类对象的地址也不相同了!

也就是说 深拷贝确实是将内部的引用对象也重新为它开辟空间!

下面看看浅拷贝和深拷贝在内存空间中的图解应该就更能理解了。

浅拷贝

深拷贝

posted @   timberwang  阅读(198)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示