Java深入理解深拷贝和浅拷贝区别[通俗易懂]

Java深入理解深拷贝和浅拷贝区别[通俗易懂]一、拷贝的引入(1)、引用拷贝创建一个指向对象的引用变量的拷贝。Teacherteacher=newTeacher("Taylor",26);Teacherotherteacher=teacher;System.out.println(teacher);System.out.println(otherteacher);输出结果:blog.Teacher@355da2…


Jetbrains全系列IDE稳定放心使用

欢迎大家关注我的公众号【老周聊架构】,Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。

一、拷贝的引入

(1)、引用拷贝

创建一个指向对象的引用变量的拷贝。

public class QuoteCopy { 
   
    public static void main(String[] args) { 
   
        Teacher teacher = new Teacher("riemann", 28);
        Teacher otherTeacher = teacher;
        System.out.println(teacher);
        System.out.println(otherTeacher);
    }
}

class Teacher { 
   
    private String name;
    private int age;

    public Teacher(String name, int age) { 
   
        this.name = name;
        this.age = 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;
    }
}

输出结果:

com.test.Teacher@28a418fc
com.test.Teacher@28a418fc

结果分析:由输出结果可以看出,它们的地址值是相同的,那么它们肯定是同一个对象。teacher和otherTeacher的只是引用而已,他们都指向了一个相同的对象Teacher(“riemann”,28)。 这就叫做引用拷贝。

在这里插入图片描述

(2)、对象拷贝

创建对象本身的一个副本。

public class ObjectCopy { 
   
    public static void main(String[] args) throws CloneNotSupportedException { 
   
        Teacher teacher = new Teacher("riemann", 28);
        Teacher otherTeacher = (Teacher) teacher.clone();
        System.out.println(teacher);
        System.out.println(otherTeacher);
    }
}

class Teacher implements Cloneable { 
   
    private String name;
    private int age;

    public Teacher(String name, int age) { 
   
        this.name = name;
        this.age = 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;
    }

    public Object clone() throws CloneNotSupportedException { 
   
        Object object = super.clone();
        return object;
    }
}

输出结果:

com.test.Teacher@28a418fc
com.test.Teacher@5305068a

结果分析:由输出结果可以看出,它们的地址是不同的,也就是说创建了新的对象, 而不是把原对象的地址赋给了一个新的引用变量,这就叫做对象拷贝。

在这里插入图片描述

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

二、浅拷贝

(1)、定义

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

简而言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。

(2)、浅拷贝实例

public class ShallowCopy { 
   
    public static void main(String[] args) throws CloneNotSupportedException { 
   
        Teacher teacher = new Teacher();
        teacher.setName("riemann");
        teacher.setAge(28);

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

        Student student2 = (Student) student1.clone();
        System.out.println("-------------拷贝后-------------");
        System.out.println(student2.getName());
        System.out.println(student2.getAge());
        System.out.println(student2.getTeacher().getName());
        System.out.println(student2.getTeacher().getAge());

        System.out.println("-------------修改老师的信息后-------------");
        // 修改老师的信息
        teacher.setName("jack");
        System.out.println("student1的teacher为: " + student1.getTeacher().getName());
        System.out.println("student2的teacher为: " + student2.getTeacher().getName());

    }
}

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;
    }
}

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;
    }

    public Object clone() throws CloneNotSupportedException { 
   
        Object object = super.clone();
        return object;
    }
}

输出结果:

-------------拷贝后-------------
edgar
18
riemann
28
-------------修改老师的信息后-------------
student1的teacher为: jack
student2的teacher为: jack

结果分析: 两个引用student1和student2指向不同的两个对象,但是两个引用student1和student2中的两个teacher引用指向的是同一个对象,所以说明是浅拷贝。

在这里插入图片描述

三、深拷贝

(1)、定义

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

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

(2)、深拷贝实例

public class DeepCopy { 
   
    public static void main(String[] args) throws CloneNotSupportedException { 
   
        Teacher teacher = new Teacher();
        teacher.setName("riemann");
        teacher.setAge(28);

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

        Student student2 = (Student) student1.clone();
        System.out.println("-------------拷贝后-------------");
        System.out.println(student2.getName());
        System.out.println(student2.getAge());
        System.out.println(student2.getTeacher().getName());
        System.out.println(student2.getTeacher().getAge());

        System.out.println("-------------修改老师的信息后-------------");
        // 修改老师的信息
        teacher.setName("jack");
        System.out.println("student1的teacher为: " + student1.getTeacher().getName());
        System.out.println("student2的teacher为: " + student2.getTeacher().getName());
    }
}

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;
    }

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

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;
    }

    public Object clone() throws CloneNotSupportedException { 
   
        // 浅复制时:
        // Object object = super.clone();
        // return object;

        // 改为深复制:
        Student student = (Student) super.clone();
        // 本来是浅复制,现在将Teacher对象复制一份并重新set进来
        student.setTeacher((Teacher) student.getTeacher().clone());
        return student;

    }
}

输出结果:

-------------拷贝后-------------
edgar
18
riemann
28
-------------修改老师的信息后-------------
student1的teacher为: jack
student2的teacher为: riemann

结果分析:
两个引用student1和student2指向不同的两个对象,两个引用student1和student2中的两个teacher引用指向的是两个对象,但对teacher对象的修改只能影响student1对象,所以说是深拷贝。

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/186946.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • expr_const在函数前与函数后的区别

    expr_const在函数前与函数后的区别const修饰常量,但是const并未区分编译时常量和运行时常量,而constexpr则只能是编译时常量,在C++11中提出。这篇文章,将详细讲解constexpr。一、常量表达式常量表达式(constexpression):指值不会改变并且在编译阶段过程就能得到计算结果的表达式。以下两种是常量表达式:constintmaxSize=10;constintlimit=maxSize+1;以下两种不是常量表达式:intstaff_size=27;cons..

    2022年9月29日
  • pytest fixtures_pytest allure

    pytest fixtures_pytest allurefixture的优势Pytest的fixture相对于传统的xUnit的setup/teardown函数做了显著的改进:命名方式灵活,不局限于setup和teardown这几个命名conf

    2022年7月30日
  • idea2023 永久激活码【在线注册码/序列号/破解码】

    idea2023 永久激活码【在线注册码/序列号/破解码】,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月18日
  • vue组件引入layui框架的table组件「建议收藏」

    vue组件引入layui框架的table组件「建议收藏」注:暂时解决了问题,以后再根据情况更新。layui框架中,layer、laydate、layim可以作为单独的模块来使用,所以可以在vue组件中直接使用,但是对于layui的其它组件,如数据表格table组件,则不能直接使用。可以通过在入口js文件加入以下代码,解决:require"**/layui.js"//**代表layui所在的路径…

    2022年6月25日
  • python怎么保留四位小数_jq四舍五入取小数点后两位

    python怎么保留四位小数_jq四舍五入取小数点后两位在很多场景的计算中,最终得到的数值例如123.45678,要截取2位小数得到123.45,而不是默认的四舍五入方法得到123.46,如何实现呢?一.小数点后取2位(四舍五入)的方法方法一:round()函数方法二:’%.2f’%f方法方法三:Decimal()函数二.小数点后取2位(四舍五不入)的方法方法一:一.小数点后取2位(四舍五入…

    2022年8月12日
  • 小程序-微信开发者工具使用教程_小程序开发教程

    小程序-微信开发者工具使用教程_小程序开发教程一、开始开发小程序的第一步,你需要拥有一个小程序帐号,通过这个帐号你就可以管理你的小程序。跟随这个教程,开始你的小程序之旅吧!二、申请帐号进入小程序注册页 (https://mp.w

    2022年8月1日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号