当前位置: 首页 > news >正文

关于Java的深拷贝和浅拷贝

文章目录

  • 1.拷贝的引入
    • 1.1引用拷贝
    • 1.2对象拷贝
  • 2.深拷贝与浅拷贝
    • 2.1浅拷贝
    • 2.2深拷贝

1.拷贝的引入

1.1引用拷贝

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

Teacher teacher = new Teacher("Taylor",26);
Teacher otherteacher = teacher;
System.out.println(teacher);
System.out.println(otherteacher);

输出:

blog.Teacher@355da254
blog.Teacher@355da254

由输出结果可以看出,它们的地址值是相同的,那么它们肯定是同一个对象。teacher和otherteacher的只是引用而已,他们都指向了一个相同的对象Teacher(“Taylor”,26)。 这就叫做引用拷贝
在这里插入图片描述

1.2对象拷贝

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

Teacher teacher = new Teacher("Swift",26);
Teacher otherteacher = (Teacher)teacher.clone();
System.out.println(teacher);
System.out.println(otherteacher);

输出:

blog.Teacher@355da254
blog.Teacher@4dc63996

由输出结果可以看出,它们的地址是不同的,也就是说创建了新的对象, 而不是把原对象的地址赋给了一个新的引用变量,这就叫做对象拷贝
在这里插入图片描述

2.深拷贝与浅拷贝

在Java语言里,当我们需要拷贝一个对象时,有两种类型的拷贝:浅拷贝与深拷贝。
浅拷贝只是拷贝了源对象的地址,所以源对象的值发生变化时,拷贝对象的值也会发生变化。
深拷贝则是拷贝了源对象的所有值,所以即使源对象的值发生变化时,拷贝对象的值也不会改变。如下图描述:
在这里插入图片描述

2.1浅拷贝

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

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

浅拷贝实例:

public class ShallowCopy {public static void main(String[] args) throws CloneNotSupportedException {Teacher teacher = new Teacher();teacher.setName("Delacey");teacher.setAge(29);Student2 student1 = new Student2();student1.setName("Dream");student1.setAge(18);student1.setTeacher(teacher);Student2 student2 = (Student2) 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("Jam");System.out.println(student1.getTeacher().getName());System.out.println(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 Student2 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;}@Overridepublic Object clone() throws CloneNotSupportedException {Object object = super.clone();return object;}}

输出

拷贝后
Dream
18
Delacey
29
修改老师的信息后-------------
Jam
Jam

结果分析: 两个引用student1和student2指向不同的两个对象,但是两个引用student1和student2中的两个teacher引用指向的是同一个对象,所以说明是浅拷贝
在这里插入图片描述

2.2深拷贝

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

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

实现深拷贝 实例1:

public class DeepCopy {public static void main(String[] args) throws Exception {Teacher2 teacher = new Teacher2();teacher.setName("Delacey");teacher.setAge(29);Student3 student1 = new Student3();student1.setName("Dream");student1.setAge(18);student1.setTeacher(teacher);Student3 student2 = (Student3) 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("Jam");System.out.println(student1.getTeacher().getName());System.out.println(student2.getTeacher().getName());}
}class Teacher2 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;}@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}}class Student3 implements Cloneable {private String name;private int age;private Teacher2 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 Teacher2 getTeacher() {return teacher;}public void setTeacher(Teacher2 teacher) {this.teacher = teacher;}@Overridepublic Object clone() throws CloneNotSupportedException {// 浅复制时:// Object object = super.clone();// return object;// 改为深复制:Student3 student = (Student3) super.clone();// 本来是浅复制,现在将Teacher对象复制一份并重新set进来student.setTeacher((Teacher2) student.getTeacher().clone());return student;}}

输出结果:

拷贝后
Dream
18
Delacey
29
修改老师的信息后-------------
Jam
Delacey

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

下图为 teacher姓名Delacey更改前:
在这里插入图片描述
下图为 teacher姓名Jam更改后:
在这里插入图片描述
利用序列化实现深拷贝:

public class DeepCopyServiable {public static void main(String[] args) throws Exception {Teacher3 t = new Teacher3();t.setName("Taylor");t.setAge(28);Student3 s1 = new Student3();s1.setAge(20);s1.setName("blank space");s1.setTeacher(t);Student3 s2 = (Student3) s1.deepClone();//拷贝System.out.println("拷贝后:");System.out.println(s2.getName());System.out.println(s2.getAge());System.out.println(s2.getTeacher().getName());System.out.println(s2.getTeacher().getAge());System.out.println("---------------------------");t.setName("swift");System.out.println("修改后:");System.out.println(s1.getTeacher().getName());System.out.println(s2.getTeacher().getName());}
}class Teacher3 implements Serializable {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 Student3 implements Serializable {private String name;private int age;private Teacher3 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 Teacher3 getTeacher() {return teacher;}public void setTeacher(Teacher3 teacher) {this.teacher = teacher;}public Object deepClone() throws Exception {// 序列化ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(this);// 反序列化ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return ois.readObject();}
}

输出结果

拷贝后:
blank space
20
Taylor
28
---------------------------
修改后:
swift
Taylor

结果分析:说明用序列化的方式实现了对象的深拷贝

参考博文(侵删):
https://blog.csdn.net/baiye_xing/article/details/71788741
https://www.cnblogs.com/ysocean/p/8482979.html
https://www.cnblogs.com/xinruyi/p/11537963.html

http://www.lryc.cn/news/14104.html

相关文章:

  • 固定值电阻的检测方法总结
  • 打印机相关
  • 入门力扣自学笔记235 C++ (题目编号:2347)
  • k8s-二进制部署
  • 前缀和差分(C/C++)
  • 回文子串的数量[寻找回文子串的完整思路过程]
  • CCNP350-401学习笔记(301-350题)
  • 【LeetCode】No.225. 用队列实现栈 -- Java Version
  • 45个写规范代码的小技巧
  • MindFusion Diagramming for Java, 最新版 Crack
  • 中间件安全—Apache常见漏洞
  • Spring IOC 容器 Bean 加载过程
  • 【DRF】Django Rest Framework(5.DRF中的通用视图类-GenericAPIView方法说明与使用说明)
  • STM32 OTA应用开发——自制BootLoader
  • 时域和频域的简单理解
  • 华为OD机试 - 第 K 个最小码值的字母 | 机试题算法思路 【2023】
  • 离散数学笔记_第一章:逻辑和证明(1)
  • Rust FFI 与C语言互相调用
  • 从全局变量寻找到Tomcat回显方式
  • Tapdata Connector 实用指南:数据入仓场景之数据实时同步到 BigQuery
  • 关于机器人状态估计(12)-VIO/VSLAM的稀疏与稠密
  • Python每日一练(20230220)
  • 技术总监的“技术提升”
  • kettle安装部署_简单认识_Spoon勺子界面---大数据之kettle工作笔记002
  • 第三章 Kafka生产问题总结及性能优化实践
  • Comparable和Comparator的区别
  • 全15万字丨PyTorch 深度学习实践、基础知识体系全集;忘记时,请时常回顾。
  • 简洁易用的记账小程序——微点记账
  • Windows平台上达梦数据库的ODBC安装与配置
  • 哈希表的介绍