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

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

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

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

结果分析:由输出结果可以看出,它们的地址值是相同的,那么它们肯定是同一个对象。teacherotherTeacher只是引用而已,他们都指向了一个相同的对象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

结果分析: 两个引用student1student2指向不同的两个对象,但是两个引用student1student2中的两个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

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

在这里插入图片描述

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

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

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


相关推荐

  • 数据库水平切分的实现原理解析---分库,分表,主从,集群,负载均衡器

    数据库水平切分的实现原理解析---分库,分表,主从,集群,负载均衡器第1章 引言        随着互联网应用的广泛普及,海量数据的存储和访问成为了系统设计的瓶颈问题。对于一个大型的互联网应用,每天几十亿的PV无疑对数据库造成了相当高的负载。对于系统的稳定性和扩展性造成了极大的问题。通过数据切分来提高网站性能,横向扩展数据层已经成为架构研发人员首选的方式。水平切分数据库:可…

    2022年6月13日
    22
  • 【时间序列预测】基于matlab CNN优化LSTM时间序列预测(单变量单输出)【含Matlab源码 1688期】「建议收藏」

    一、CNN简介二、LSTM简介1LSTM控制流程LSTM的控制流程:是在前向传播的过程中处理流经细胞的数据,不同之处在于LSTM中细胞的结构和运算有所变化。这一系列运算操作使得LSTM具有能选择保存信息或遗忘信息的功能。咋一看这些运算操作时可能有点复杂,但没关系下面将带你一步步了解这些运算操作。2核心概念LSTM的核心概念在于细胞状态以及“门”结构。细胞状态相当于信息传输的路径,让信息能在序列连中传递下去。你可以将其看作网络的“记忆”。理论上讲,细胞状态能够将序列处理过程中的相关

    2022年4月16日
    79
  • provideoplayer2中文教程_potplayer vr

    provideoplayer2中文教程_potplayer vrPotplayer是高清影视常用的播放器,界面简洁,功能齐全,比MPC-HC和MPC-BE更人性化;但其默认方案十分糟糕,预设过多错误,无法正确播放10-bit视频,一直饱受诟病。VCB-Stuido以往发布的数篇高清教程大多偏重于madVR,在PotPlayer的设置方面有些错漏。为了广大观众能正确、便捷地用PotPlayer享受高清影视,我们为大家带来一篇基于Pot…

    2022年9月14日
    2
  • elemtype到底是个啥?

    elemtype到底是个啥?以前对这个东西的一知半解,今天有时间,查了多方面的资料,总结下:ElemType简单来说就是:用来更好的替代,他也可以叫做别的名字,比如说:#defineElemTypeint写程序,就可以用ElemType来进行替代int,若以后想要改Elemtype所定义的数据类型为char,直接#defineElemTypechar只要是其涉及到的全部修改了数据类型,可以修改最少量的代码,…

    2022年5月12日
    101
  • visio 2003密钥

    visio 2003密钥序列号:GWH28-DGCMP-P6RC4-6J4MT-3HFDY序列号:WFDWY-XQXJF-RHRYG-BG7RQ-BBDHM

    2022年6月24日
    59
  • navicat15 mac永久激活码(JetBrains全家桶)2022.02.26[通俗易懂]

    (navicat15 mac永久激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~2…

    2022年4月1日
    206

发表回复

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

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