关于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
相关文章:

关于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…...

固定值电阻的检测方法总结
🏡《总目录》 目录 1,概述2,测量方法3,检测方法3.1,读值3.2,测量3.3,排故4,总结1,概述 本文简单总结固定值电阻的测量与检查方法要点和注意事项。 2,测量方法 对于固定值电阻的测量来讲,直接将万用表红黑表笔分别插入到如下图所示的红色和黑色接线端。然后将万用表…...
打印机相关
打印机相关 打印机协议 ipp,printer-job-language,lpd协议。他们的默认端口分别是631,9100和515. printer-job-language(RAW协议) 9100端口的printer-job-language,又称为RAW协议。目前遇到的问题是,此端口发送数据,打印机直接打印,除非发送正确的printer-job-lan…...
入门力扣自学笔记235 C++ (题目编号:2347)
2347. 最好的扑克手牌 题目: 给你一个整数数组 ranks 和一个字符数组 suit 。你有 5 张扑克牌,第 i 张牌大小为 ranks[i] ,花色为 suits[i] 。 下述是从好到坏你可能持有的 手牌类型 : "Flush":同花&…...

k8s-二进制部署
文章目录一、环境二、步骤1、安装cfssl工具2、部署etcd集群3、在node节点安装docker组件4、安装flannel组件部署master节点组件部署node节点部署kube-proxy组件三、测试一、环境 角色服务器地址组件master192.168.174.140kube-apiserver,kube-controller-manager&a…...

前缀和差分(C/C++)
目录 1. 前缀和的定义 2. 一维前缀和 2.1 计算公式 2.2 用途 2.3 小试牛刀 3. 二维前缀和 3.1 用途 1. 前缀和的定义 对于一个给定的数列A,他的前缀和数中 S 中 S[ i ] 表示从第一个元素到第 i 个元素的总和。 如下图:绿色区域的和就是前缀和数组…...

回文子串的数量[寻找回文子串的完整思路过程]
寻找回文子串的完整思路过程前言一、回文串的数量二、动态规划1、完整思考过程2、go总结参考文献前言 回文字符串,就是从左遍历和从右遍历的字符是相同顺序的,转换一下,就是该字符串是对称的。寻找回文子串面临两个直接的问题,1-…...

CCNP350-401学习笔记(301-350题)
301、Drag and drop the virtual component from the left onto their descriptions on the right. 302、Which two actions, when applied in the LAN network segment, will facilitate Layer 3 CAPWAP discovery for lightweight AP? (Choose two.)A. Utilize DHCP option …...

【LeetCode】No.225. 用队列实现栈 -- Java Version
题目链接:https://leetcode.cn/problems/implement-stack-using-queues/ 1. 题目介绍(225. 用队列实现栈) 请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、t…...

45个写规范代码的小技巧
目录 1、规范命名 2、规范代码格式 3、写好代码注释 4、try catch 内部代码抽成一个方法 5、方法别太长 6、抽取重复代码 7、多用return 8、if条件表达式不要太复杂 9、优雅地参数校验 10、统一返回值 11、统一异常处理 12、尽量不传递null值 13、尽量不返回null值…...

MindFusion Diagramming for Java, 最新版 Crack
Diagramming for Java, V4.6.1 A unique Java Swing library for any type of flowchart.您需要的每一个图表功能 图表、方案、图形、网络、算法、树、图表 - 所有这些都是使用 MindFusion Diagramming for Java 工具快速轻松地构建的。结果令人着迷。 Java Dagram 库ÿ…...

中间件安全—Apache常见漏洞
中间件安全—Apache常见漏洞1.Apache常见漏洞1.1.Apache介绍1.2.Apache HTTPD 换行解析漏洞(CVE-2017-15715)1.2.1.漏洞介绍1.2.2.漏洞环境1.2.2.1.运行漏洞环境1.2.2.2.访问漏洞环境1.2.3.漏洞复现1.2.3.1.拦截1.2.3.2.添加换行1.2.3.3.访问文件1.3.Apa…...

Spring IOC 容器 Bean 加载过程
Spring IOC 容器 Bean 加载过程 Spring 对于我们所有的类对象进行了统一抽象,抽象为 BeanDefinition ,即 Bean 的定义,其中定义了类的全限定类名、加载机制、初始化方式、作用域等信息,用于对我们要自动装配的类进行生成。 Sprin…...
【DRF】Django Rest Framework(5.DRF中的通用视图类-GenericAPIView方法说明与使用说明)
1. GenericAPIView [通用视图类],概述 继承自 APIView增加了操作序列化器和数据库查询的方法,作用是为下面Mixin扩展类的执行提供方法支持。通常在使用时,可搭配一个或者多个Mixin扩展类源码 当我们查看 GenericAPIView 的源码时,…...

STM32 OTA应用开发——自制BootLoader
STM32 OTA应用开发——自制BootLoader 目录STM32 OTA应用开发——自制BootLoader前言1 环境搭建2 BootLoader工作原理以及常见分区介绍3 BootLoader的制作4 烧录下载配置5 运行测试结束语前言 什么是OTA? 百度百科:空中下载技术(Over-the-Ai…...
时域和频域的简单理解
目录文章背景结论举例说明说回频域连续或离散总结文章背景 时域和频域在傅里叶变换和拉普拉斯变换,z变换中经常提到的高频词。本文的重点就是想说明怎么理解 “频域” 这个名词。 结论 频域就是一个信号 所有组成频率的取值范围的集合 举例说明 以大家从中小学开…...
华为OD机试 - 第 K 个最小码值的字母 | 机试题算法思路 【2023】
最近更新的博客 华为OD机试 - 简易压缩算法(Python) | 机试题算法思路 【2023】 华为OD机试题 - 获取最大软件版本号(JavaScript) 华为OD机试 - 猜字谜(Python) | 机试题+算法思路 【2023】 华为OD机试 - 删除指定目录(Python) | 机试题算法思路 【2023】 华为OD机试 …...

离散数学笔记_第一章:逻辑和证明(1)
1.1命题逻辑1.1.1 命题 1.1.2 逻辑运算符 定义1: 否定联结词定义2: 合取联结词定义3: 析取联结词定义4: 异或联结词1.1.3 条件语句 定义5: 条件语句定义6: 双条件语句1.1.1 命题 1.命题:是…...
Rust FFI 与C语言互相调用
参考 https://cloud.tencent.com/developer/article/2077534 https://github.com/shepmaster/rust-ffi-omnibus cbindgen 简介 二进制方式构建 $ cargo install cbindgen //默认构建C头文件 C语言需要 --lang C $ cd /path/to/my/project && cbindgen . -o target/…...

从全局变量寻找到Tomcat回显方式
前言 对于回显的获取主要是在ApplicationFilterChain类的lastServicedRequest / lastServicedResponse两个属性,是使用的ThreadLocal进行修饰的,并且,在执行请求的过程中,通过反射修改属性值,能够记录下当前线程的req…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...
高防服务器价格高原因分析
高防服务器的价格较高,主要是由于其特殊的防御机制、硬件配置、运营维护等多方面的综合成本。以下从技术、资源和服务三个维度详细解析高防服务器昂贵的原因: 一、硬件与技术投入 大带宽需求 DDoS攻击通过占用大量带宽资源瘫痪目标服务器,因此…...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...