Java基础-复制

复制

    • 前言
    • 引用拷贝
    • 浅拷贝
    • 深拷贝
      • 重写clone()方法
      • 序列化

前言

在编码中,我们可能会遇到需要将对象的属性复制到另一个对象中,这种情况叫做拷贝.
拷贝与Java内存结构有密切关系,拷贝有三种情况,引用拷贝,深拷贝和浅拷贝,下面来了解一下.

引用拷贝

引用拷贝会生成一个新的对象引用地址,但是他们最终指向依然是同一个对象.
举个例子来说:
一个人可以有多个名字,比如我中文名叫王一,英文名叫Ian(开头大写i),这两个名字指的都是我.
参考下图
在这里插入图片描述
代码示例:

class Son {String name;int age;public Son(String name, int age) {this.name = name;this.age = age;}
}
public class test {public static void main(String[] args) {Son s1 = new Son("son1", 12);Son s2 = s1;s1.age = 22;System.out.println(s1);System.out.println(s2);System.out.println("s1的age:" + s1.age);System.out.println("s2的age:" + s2.age);System.out.println("s1==s2" + (s1 == s2));//相等}
}

输出的结果为:

Son@135fbaa4
Son@135fbaa4
s1的age:22
s2的age:22
true

浅拷贝

如果我们只是想将目标对象的内容复制过来而不是直接拷贝引用,那么使用浅拷贝是很好的方式.
浅拷贝概念: 浅拷贝会创建一个对象,新对象和原对象本身没有任何关系,新对象和原对象不相等,但是新对象的属性和老对象相同.
具体可以看如下区别:

  • 属性是基本类型(int,double,long,boolean等)
    拷贝的是基本类型的值
  • 属性是引用类型
    拷贝的是内存地址(即复制引用但不复制引用的对象),因为如果其中一个对象改变了这个地址,就会影响到另一个对象.
    如下图:
    在这里插入图片描述
    那么如何实现浅拷贝呢?
    在需要拷贝的类上实现Cloneable接口并重写其clone(方法)
    为什么要重写呢?
    重写是为了扩大访问权限,如果不重写,Object的clone方法的修饰符是protected,除了与Object同包(java.lang)和直接子类能访问,其他类无权访问。
@Override
protected Object clone() throws CloneNotSupportedException {return super.clone();
}

在使用的时候直接调用类的clone()方法即可.如下

class Father{String name;public Father(String name) {this.name=name;}@Overridepublic String toString() {return "Father{" +"name='" + name + '\'' +'}';}
}
class Son implements Cloneable {int age;String name;Father father;public Son(String name,int age) {this.age=age;this.name = name;}public Son(String name,int age, Father father) {this.age=age;this.name = name;this.father = father;}@Overridepublic String toString() {return "Son{" +"age=" + age +", name='" + name + '\'' +", father=" + father +'}';}@Overrideprotected Son clone() throws CloneNotSupportedException {return (Son) super.clone();}
}
public class test {public static void main(String[] args) throws CloneNotSupportedException {Father f=new Father("bigFather");Son s1 = new Son("son1",13);s1.father=f;Son s2 = s1.clone();System.out.println(s1);System.out.println(s2);System.out.println("s1==s2:"+(s1 == s2));//不相等System.out.println("s1.name==s2.name:"+(s1.name == s2.name));//相等System.out.println();//但是他们的Father father 和String name的引用一样s1.age=12;s1.father.name="smallFather";//s1.father引用未变s1.name="son222";//类似 s1.name=new String("son222") 引用发生变化System.out.println("s1.Father==s2.Father:"+(s1.father == s2.father));//相等System.out.println("s1.name==s2.name:"+(s1.name == s2.name));//不相等System.out.println(s1);System.out.println(s2);}
}

在这里插入图片描述

深拷贝

如何绝对的拷贝这个对象,使这个对象完全独立于原对象?
这时候可以使用深拷贝.
在实际使用时,我们肯定是希望新拷贝出来的对象不受原对象的影响,否则咱们做出拷贝的意义何在?(我就碰到过因为对象被同事插进来的代码导致对象发生了变更,代码出现BUG的问题,后面是使用的深拷贝才消除同事的代码对该对象的影响)
深拷贝概念:
在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量.
在这里插入图片描述
在具体实现深拷贝上,这里提供两个方式,重写clone()方法和序列法

重写clone()方法

如果要使用这种方法,那么就要将类中所有自定义引用变量的类也实现Cloneable接口实现clone()方法

//Father clone()方法
@Override
protected Father clone() throws CloneNotSupportedException {return (Father) super.clone();
}
//Son clone()方法
@Override
protected Son clone() throws CloneNotSupportedException {Son son= (Son) super.clone();//待返回克隆的对象son.name=new String(name);son.father=father.clone();return son;
}

结果如下:

Son{age=13, name='son1', father=Father{name='bigFather'}}
Son{age=13, name='son1', father=Father{name='bigFather'}}
s1==s2:false
s1.name==s2.name:falses1.Father==s2.Father:false
s1.name==s2.name:false
Son{age=12, name='son222', father=Father{name='smallFather'}}
Son{age=13, name='son1', father=Father{name='bigFather'}}

序列化

如果引用数量太多,或者层数太多了使用深拷贝会让人绝望!
那么我们可以使用序列化的方式来实现深拷贝
在这里插入图片描述
序列化后,将二进制字节流内容写到一个媒介(文本或字符数组),然后通过这个媒介读取数据,原对象写入这个媒介后拷贝给clone对象,原对象的修改不会影响clone对象,因为clone对象是从这个媒介读取的.
熟悉对象缓存的知道Java对象存在Redis中,在Redis中读取出来生成Java对象,这就需要用到序列化和反序列化.
一般是将Java对象存储为字节流或者Json串然后反序列化成Java对象.
因为序列化会储存对象的属性但是无法存储对象在内存中地址相关信息,所以在反序列化成Java对象的时候会重新创建所有的引用对象.
具体实现上:
自定义类需要实现Serializable接口,在需要深拷贝的类(Son)中定义一个函数返回该类对象.

protected Son deepClone() throws IOException, ClassNotFoundException {Son son=null;//在内存中创建一个字节数组缓冲区,所有发送到输出流的数据保存在该字节数组中//默认创建一个大小为32的缓冲区ByteArrayOutputStream byOut=new ByteArrayOutputStream();//对象的序列化输出ObjectOutputStream outputStream=new ObjectOutputStream(byOut);//通过字节数组的方式进行传输outputStream.writeObject(this);  //将当前student对象写入字节数组中//在内存中创建一个字节数组缓冲区,从输入流读取的数据保存在该字节数组缓冲区ByteArrayInputStream byIn=new ByteArrayInputStream(byOut.toByteArray()); //接收字节数组作为参数进行创建ObjectInputStream inputStream=new ObjectInputStream(byIn);son=(Son) inputStream.readObject(); //从字节数组中读取return  son;
}

结果

Son{age=13, name='son1', father=Father{name='bigFather'}}
Son{age=13, name='son1', father=Father{name='bigFather'}}
s1==s2:false
s1.name==s2.name:falses1.Father==s2.Father:false
s1.name==s2.name:false
Son{age=12, name='son222', father=Father{name='smallFather'}}
Son{age=13, name='son1', father=Father{name='bigFather'}}

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

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

相关文章

15届蓝桥杯第二期模拟赛题单详细解析

文章目录 🧡🧡t1_求余🧡🧡思路代码 🧡🧡t2_灌水🧡🧡思路代码 🧡🧡t3_字符显示🧡🧡思路代码 🧡🧡t4_区间最大和…

携手共进办公网络安全

一、引言 在数字化时代的今天,办公网络安全问题已日益成为企业发展的重要课题。随着信息技术的快速发展,网络安全威胁也呈现出多样化、复杂化的趋势。这些危害可能源于网络本身的漏洞、人为因素或外部威胁,给企业的信息安全和正常运营带来严…

游戏组队新姿势!Xinstall一键拉起,好友秒速加入你的战队!

在如今的游戏世界中,与好友一起组队开黑已成为一种潮流。然而,繁琐的组队过程往往让玩家们望而却步。这时,你需要一款强大的辅助工具——Xinstall,它是一站式App全渠道统计服务商,专注于提供App传参安装、全渠道广告效…

springboot274基于web的电影院购票系统

电影院购票系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装电影院购票系统软件来发挥其高效…

strcmp的模拟实现

一:strcmp函数的定义: strcmp函数功能的解释: 比较两个字符串的大小(按照字符串中字符的ascll码值)。 标准规定: 第一个字符串大于第二个字符串,则返回大于 0 的数字 第一个字符串等于第二个…

市场复盘总结 20240315

仅用于记录当天的市场情况,用于统计交易策略的适用情况,以便程序回测 短线核心:不参与任何级别的调整,采用龙空龙模式 一支股票 10%的时候可以操作, 90%的时间适合空仓等待 二进三: 进级率中 0% 最常用的二…

【Linux】IPC-信号

💻文章目录 📄前言信号概念信号阻塞概念 信号的处理信号的使用 📓总结 📄前言 信号,一种无论是生活还是编程都离不开的东西。生活中,我们通过信号来对外部发生的事情进行反应,就好像你的手机来了…

Vue.js+SpringBoot开发个人健康管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 健康档案模块2.2 体检档案模块2.3 健康咨询模块 三、系统展示四、核心代码4.1 查询健康档案4.2 新增健康档案4.3 查询体检档案4.4 新增体检档案4.5 新增健康咨询 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpri…

程序员必备开发工具、程序员必备集成开发环境(IDE)

🌟 前言 欢迎来到我的技术小宇宙!🌌 这里不仅是我记录技术点滴的后花园,也是我分享学习心得和项目经验的乐园。📚 无论你是技术小白还是资深大牛,这里总有一些内容能触动你的好奇心。🔍 &#x…

CTP-API开发系列之十:v6.7.0-Python版封装(Windows/Linux)(附源码)

CTP-API开发系列之十:v6.7.0-Python版封装(Windows/Linux)(附源码) CTP-API开发系列之十:v6.7.0-Python版封装(Windows/Linux)(附源码)资源获取准备工作Windo…

2023年全球软件质量效能大会(QECon上海站):智慧碰撞,质量与效能的新篇章(附大会核心PPT资料下载)

在数字化浪潮席卷全球的今天,软件行业正以前所未有的速度发展。作为推动这一进程的重要力量,软件质量与效能的提升显得尤为关键。2023年全球软件质量&效能大会(QECon上海站)的盛大召开,无疑为业界提供了一次难得的…

【b站咸虾米】2 Vue基础(上) 2021最新Vue从基础到实例高级_vue2_vuecli脚手架博客案例

课程地址:【2021最新Vue从基础到实例高级_vue2_vuecli脚手架博客案例】 https://www.bilibili.com/video/BV1pz4y1S7bC/?share_sourcecopy_web&vd_sourceb1cb921b73fe3808550eaf2224d1c155 目录 2 Vue基础 上 2.0 补充知识 2.0.1 Vue实例的作用范围 2.0.2 t…

50、东北大学、阿尔伯塔大学:Hi-GCN从2个层次角度进行图学习,用来诊断脑部疾病[你这和MVS-GCN套娃呢?]

本文由东北大学医学图像智能计算教育部重点实验室&#xff0c;加拿大阿尔伯塔大学于2020年10.24日发表于<Computers in Biology and Medicine> JCR\IF: Q1\7.7 Abstract&#xff1a; 目的:近年来&#xff0c;脑连接网络已被用于神经系统疾病的分类&#xff0c;如自闭症…

【论文翻译】UP-DETR—Unsupervised Pre-training for Detection Transformers

0.论文摘要 摘要——通过Transformer model编码器——解码器架构&#xff0c;用于目标检测的检测Transformer model&#xff08;DETR&#xff09;达到了与Faster R-CNN相比具有竞争力的性能。然而&#xff0c;使用scratch transformers训练&#xff0c;DETR需要大规模的训练数…

【docker】docker的常用命令

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;中间件 ⛺️稳中求进&#xff0c;晒太阳 常规命令 docker version #查看docker 版本信息docker info #显示docker 的系统信息&#xff0c;包括镜像和容器数量docker --help #查看所有的命…

如何发布新闻稿?如何让媒体记者报道自己的企业?

目前&#xff0c;很多企业和个人创业者都知道用新闻稿或软文来做宣传&#xff0c;但是一般只可以发布到自己的微信公众号、百家号等自媒体平台&#xff0c;往往收效甚微。有企业找到小马识途营销顾问咨询原因&#xff0c;小马识途营销顾问分析自媒体上发软文效果不明显的原因主…

【超图】SuperMap如何使知识图谱与BIM数据的绑定

作者&#xff1a;taco 近两年知识图谱的概念突然大火了起来&#xff0c;随之而来的就是用户的各种需求&#xff0c;你们的知识图谱能干什么呢&#xff1f;知识图谱有哪些应用呢&#xff1f;在结合客户的一些需求&#xff0c;以及自身的一些想法&#xff0c;写下这篇文章。 一、…

MySQL的insert-on-duplicate语句详解

一、insert-on-duplicate语句语法 注意&#xff1a;ON DUPLICATE KEY UPDATE只是 MySQL的特有语法&#xff0c;并不是SQL标准语法&#xff01; INSERT INTO … ON DUPLICATE KEY UPDATE 是 MySQL 中一种用于插入数据并处理重复键冲突的语法。 这个语法适用于在 insert的时候…

抖音直播招聘的主要优势有哪些?

触达广泛受众抖音拥有海量活跃用户,通过直播可以瞬间吸引大量观众关注。相比传统招聘渠道,抖音直播能够触达到更广泛、更多样化的人才群体。 提升品牌形象在直播中,企业可以展现自身独特的企业文化和价值观,增强与观众的互动交流,有助于提升品牌形象和美誉度。 精准招聘定位企业…

Java项目:53 springboot校园管理系统的设计与实现014

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 1、关于校园管理系统的基本要求&#xff1a; &#xff08;1&#xff09;功能要求&#xff1a;可以管理首页、个人中心、院校管理、用户管理、单位类别…