Java深浅拷贝

文章目录

目录

文章目录

前言

1) 引用拷贝

2) 对象拷贝

二 . 浅拷贝

1) 拷贝构造方法实现浅拷贝

2) 工厂方法实现浅拷贝

3) clone方法实现浅拷贝

三 . 深拷贝

1) 通过重写clone方法来实现深拷贝

2) 通过对象序列化实现深拷贝


前言

大家好,今天给大家带来的是java中的深浅拷贝


一 . 拷贝的引入

1) 引用拷贝

引用拷贝通常指的是浅拷贝,即只复制了对象本身,而没有复制对象内部的引用对象。这意味着原始对象和拷贝对象仍然共享相同的引用对象

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

Student s1 = new Student("张三",23);
Student s2 = s1;
System.out.println(s1);
System.out.println(s2);

2) 对象拷贝

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

Student student = new Student("张三",23);
Student otherStudent = (Student)student.clone();
System.out.println(student);
System.out.println(otherStudent);

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

Java中的对象拷贝(Object Copy)指的是将一个对象的所有属性(成员变量)拷贝到另一个有着相同类类型的对象中去。

在程序中拷贝对象是很常见的,主要是为了在新的上下文环境中复用现有对象的部分或全部 数据。

Java中的对象拷贝主要分为:浅拷贝(Shallow Copy)、深拷贝(Deep Copy)。

二 . 浅拷贝

浅拷贝是指在拷贝对象时,只复制对象本身,而不复制对象内部的引用对象。这意味着原始对象和拷贝对象会共享相同的引用对象,如果引用对象发生改变,原始对象和拷贝对象都会受到影响。

①对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。

②对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。

在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。

浅拷贝的实现方式主要有三种

1) 拷贝构造方法实现浅拷贝

class Person {Age age;String name;public Person(Age age, String name) {this.age = age;this.name = name;}/*** 拷贝构造方法* @param p*/public Person(Person p){this.age = p.age;this.name = p.name;}}class Age{int age;public Age(int age) {this.age = age;}
}
Age age = new Age(18);
Person person1 = new Person(age,"张三");
Person person2 = new Person(person1);
System.out.println(person1);
System.out.println(person2);

 

2) 工厂方法实现浅拷贝

改变一个方法就行,其他的不变

    /*** 工厂方法* @param p*/public Person clone(Person p){return new Person(p.age,p.name);}

3) clone方法实现浅拷贝

Object类是类结构的根类,其中有一个方法为protected Object clone() throws CloneNotSupportedException,这个方法就是进行的浅拷贝。有了这个浅拷贝模板,我们可以通过调用clone()方法来实现对象的浅拷贝。

但是需要注意:

1、Object类虽然有这个方法,但是这个方法是受保护的(被protected修饰),所以我们无法直接使用。

2、使用clone方法的类必须实现Cloneable接口,否则会抛出异常CloneNotSupportedException。

对于这两点,我们的解决方法是,在要使用clone方法的类中重写clone()方法,通过super.clone()调用Object类中的原clone方法

public class ShallowCopy {public static void main(String[] args) throws CloneNotSupportedException {Age age = new Age(18);Person person1 = new Person(age,"张三");Person person2 = (Person)person1.clone();System.out.println(person1);System.out.println(person2);}
}class Person implements Cloneable{Age age;String name;public Person(Age age, String name) {this.age = age;this.name = name;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}class Age{int age;public Age(int age) {this.age = age;}
}

三 . 深拷贝

深拷贝指的是在复制对象时,不仅复制了对象本身,还复制了对象内部的所有引用对象,使得原始对象和拷贝对象完全独立,彼此不会相互影响。

在进行深拷贝时,需要递归地复制对象及其内部的所有引用对象,确保每个对象都是独立的

浅拷贝示意图

深拷贝示意图

如果Age对象依然关联其他引用对象,同样也是需要拷贝的

深拷贝的实现方法主要有两种

1) 通过重写clone方法来实现深拷贝

class Animal implements Cloneable{int age;String name;Dog dog;public Animal(int age, String name, Dog dog) {this.age = age;this.name = name;this.dog = dog;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Dog getDog() {return dog;}public void setDog(Dog dog) {this.dog = dog;}@Overrideprotected Object clone() throws CloneNotSupportedException {Animal animal = (Animal)super.clone();animal.setDog((Dog)animal.getDog().clone());return animal;}
}class Dog implements Cloneable{int age;String name;public Dog(int age, String name) {this.age = age;this.name = name;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
Animal animal = new Animal(1,"小黄",new Dog(1,"小黄"));
Animal cloneAnimal = (Animal) animal.clone();
System.out.println(animal);
System.out.println(cloneAnimal);
System.out.println(animal.getDog());
System.out.println(cloneAnimal.getDog());

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

2) 通过对象序列化实现深拷贝

虽然层次调用clone方法可以实现深拷贝,但是显然代码量实在太大。特别对于属性数量比较多、层次比较深的类而言,每个类都要重写clone方法太过繁琐。

将对象序列化为字节序列后,默认会将该对象的整个对象图进行序列化,再通过反序列即可完美地实现深拷贝。

参考代码如下

import java.io.*;class MyClass implements Serializable {int number;public MyClass(int number) {this.number = number;}
}public class DeepCopyExample {public static void main(String[] args) {// 创建一个原始对象MyClass originalObject = new MyClass(10);// 使用序列化和反序列化进行深拷贝MyClass copiedObject = deepCopy(originalObject);// 修改原始对象的值originalObject.number = 20;// 打印拷贝对象的值,验证是否进行了深拷贝System.out.println(copiedObject.number);  // 输出 10}// 使用序列化和反序列化进行深拷贝public static <T extends Serializable> T deepCopy(T object) {try {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();ObjectOutputStream output = new ObjectOutputStream(outputStream);output.writeObject(object);ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());ObjectInputStream input = new ObjectInputStream(inputStream);return (T) input.readObject();} catch (Exception e) {e.printStackTrace();return null;}}
}

 总结

这篇文章这要给大家介绍了一下java中的深浅拷贝,我们下一篇博客见

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/299068.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

02.WebLogic 高级管理与维护

以14c为主&#xff0c;11g,12c为辅 01 weblogic server 启动停止流程 1.1weblogic server 启动 linux中 nohup ./startWebLogic.sh & 那如果这台机器有三个版本同时启动&#xff0c;如何解决&#xff1f; 第一步&#xff1a; cd /weblogic #cd到你的weblogic vi sta…

Zabbix监控原理概括

一、zabbix工作流程 zabbix监控是将zabbix客户端要安装在被监控设备上负责收集数据&#xff0c;并将数据发送给zabbix服务端&#xff0c;将zabbix客户端接收或采集的数据存储在数据库中。 zabbix的数据收集分为两种模式&#xff1a; 1、主动模式 zabbix客户端主动向zabbix …

二丙二醇甲醚,预计将以 5% 左右的较高复合年增长率增长

二丙二醇甲醚 (DPM) 是一种无色、水溶性、低毒的化合物&#xff0c;广泛应用于油漆和涂料、粘合剂和密封剂、清洁产品和化学加工等各种最终用途行业。DPM 衍生自环氧丙烷&#xff0c;由于其低挥发性和良好的溶解性能而被用作溶剂。全球市场分析&#xff1a; 在预测期内&#xf…

微信小程序开发系列-03全局配置中的“window”和“tabBar”

本文继续学习下全局配置中的“window”和“tabBar”。 window 用于设置小程序的导航栏、标题、窗口颜色等。&#xff08;吐槽一句&#xff0c;官网这里的属性描述真的让人看不懂&#xff0c;只有靠自己实际运行调试才能知道是什么意思。&#xff09; 导航栏 设置导航栏背景色…

短视频矩阵软件哪个好用?

短视频频矩阵软件是一种可以帮助用户快速制作、发布和管理多个个短视频账号的工具&#xff0c;它可以让用户在不同的平台上展示自己的内容&#xff0c;提高品牌知名度和影响力&#xff0c;同时也可以节省时间和精力&#xff0c;提升效率和质量。。短视频频矩阵软件有很多种&…

spark:RDD编程(Python版)

RDD运行原理 RDD设计背景 许多选代目前的MapReduce框架都是把中间结果写入到稳定存储 (比如磁盘)中带来了大量的数据复制、磁盘IO和序列化开销 RDD就是为了满足这种需求而出现的&#xff0c;它提供了一个抽象的数据架构&#xff0c;我们不必担心底层数据的分布式特性&#xf…

NeurIPS已成为了AI人才招聘的最大盛会,连Hinton都“应聘”过

在一周前美国举行的年度最热门的人工智能大会NeurIPS 2023上&#xff0c;有超过1万名世界顶尖AI研究人员聚集在此。 而除了研究员之外&#xff0c;中国科技公司和华尔街公司是其中最突出的参会者&#xff0c;他们都背负着抢夺AI人才的任务。 大模型人才最受欢迎 随着今年Cha…

unityc用vs2017介绍

21版unity能用17vs&#xff0c;只要在unity的Edit/Preferences/ExternalTools里面改既可。

【网安 | 网络协议】ARP协议(地址解析协议)

前言 在使用nmap时可以使用-PR指令&#xff0c;通过发送ARP请求包进行主机存活探测。 那么这一过程的原理是什么呢&#xff1f; 在了解什么是ARP协议后&#xff0c;问题就迎刃而解了。 概念 地址解析协议&#xff0c;即ARP&#xff08;Address Resolution Protocol&#xf…

大三了,C++还算可以从事什么岗位比较好?

大三了&#xff0c;C还算可以从事什么岗位比较好&#xff1f; 在开始前我有一些资料&#xff0c;是我根据自己从业十年经验&#xff0c;熬夜搞了几个通宵&#xff0c;精心整理了一份「c的资料从专业入门到高级教程工具包」&#xff0c;点个关注&#xff0c;全部无偿共享给大家…

设计模式--工厂方法模式

实验3&#xff1a;工厂方法模式 本次实验属于模仿型实验&#xff0c;通过本次实验学生将掌握以下内容&#xff1a; 1、理解工厂方法模式的动机&#xff0c;掌握该模式的结构&#xff1b; 2、能够利用工厂方法模式解决实际问题。 [实验任务]&#xff1a;加密算法 目前常用…

渗透测试 | 信息收集常用方法合集

目录 一、关于域名 1.子域名收集 a.搜索引擎查找 b.在线查询 c.工具 d.SSL/TLS证书查询 2.端口型站点收集 3.目录文件扫描 a.目录扫描工具 b.github搜索 c.google搜索 d.在线网站 e.文件接口工具 4.旁站和C段 a.旁站查询 b.C段查询 5.网站技术架构信息 a.基础…