Java之Clonable接口和深浅拷贝

Clonable接口

我们船舰了一个人的对象,想要克隆一个一模一样的对象,可以用到object类里面的克隆方法

object不是所有类的父类吗?那为什么用person1点不出这个方法呢?可以看一下源码

这是Object类里面的clone方法的声明,native说明这是本地方法,底层是由c/c++实现的。注意,它的访问权限是protected,所以再不同包中的子类只可以用super来引用,但super又不能静态方法中使用,所以我们只能再Person类里面重写一个方法,如下:

但还是报错,注意throws CloneNotSupportedException表示克隆不支持异常,语法规定,我们需要在main方法后面也加上这一句,同时,clone方法的返回值是Object类型,但在main方法中我们用了它的子类来接收,这是向下转型,必须要用括号强转,如下:

但还是报错,这就是 CloneNotSupportedException,即不支持克隆,那么这时,Clonable接口就起作用了,我们需要让那个被克隆的类去实现Clonable接口,如下:

空接口/标记接口

我们再看一下接口的源码:

发现里面没有任何抽象方法,这就是一个空接口或者叫标记接口,表示该类可以被拿去克隆

将上面的错误全部修正后,person1就可以被克隆了

深拷贝与浅拷贝

现在,我们再在person类里面加一个成员变量money,它是Money类的

class Money{public double m=29.9;}
class Person implements Cloneable{public String name;public int age;public Money money=new Money();public Person(String name, int age) {this.name = name;this.age = age;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
public class Test {public static void main(String[] args)throws CloneNotSupportedException  {Person person1=new Person("张三",20);Person person2=(Person)person1.clone();System.out.println("person1:"+person1.money.m);System.out.println("person1:"+person2.money.m);System.out.println("==========");person1.money.m=99.9;System.out.println("person1:"+person1.money.m);System.out.println("person1:"+person2.money.m);}
}

如上,那输出的结果是什么?

浅拷贝

按理说,即使person2是克隆出来的,但它也是一个独立的个体,应该不会受person1的影响,可却出现了上面的现象,实际上,在拷贝money时,由于money是个引用类型,它的值是所指对象的地址,在拷贝时,就将person1的money的值直接给到了person2的money,导致两个money都指向了同一个对象,而不是我们想看到的不是同一个对象而只是有一样的值罢了。

这种对于money的拷贝就是浅拷贝

深拷贝

那如何进行深拷贝?其实就是再给person2的money另外开辟一块空间,然后再将person1的money所指对象的值拷贝到person2的money所指对象。既然要克隆money,那么就要让money也支持克隆,如下

第二张图的第二行代码是刚刚的浅拷贝,在它的基础上再将money也拷贝一份,就能实现真正意义上的一式两份,也就是深拷贝。那么我们如何将二三行代码合在一起?先看一下重写的克隆方法:

这个方法是放在哪个类就克隆哪个类,由于在person类里面重写的clone方法仅支持person的克隆,所以我们可以修改这个克隆方法使他还可以将内部的money也克隆一份,而不仅仅是克隆其表面的值,如下:

可是,这个代码有很大的问题,当我们用this.clone时,就会出现死循环,一i那位这是自己调用了自己,所以应该修改为用Object类的clone方法,即用到super,如下:

这时修改1的值就不会影响2了

最终代码就是

class Money implements Cloneable{@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}public double m=29.9;}
class Person implements Cloneable{public String name;public int age;public Money money=new Money();public Person(String name, int age) {this.name = name;this.age = age;}@Overrideprotected Object clone() throws CloneNotSupportedException {Person tmp=(Person) super.clone();Money money=(Money) this.money.clone();tmp.money=money;return tmp;}
}
public class Test {public static void main(String[] args)throws CloneNotSupportedException  {Person person1=new Person("张三",20);Person person2=(Person)person1.clone();//person2.money= (Money) person1.money.clone();System.out.println("person1:"+person1.money.m);System.out.println("person2:"+person2.money.m);System.out.println("==========");person1.money.m=99.9;System.out.println("person1:"+person1.money.m);System.out.println("person2:"+person2.money.m);

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

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

相关文章

HackTheBox-Machines--Analytics

文章目录 1 端口扫描2 测试思路3 漏洞探测4 权限获取5 权限提升 Analytics 测试过程 1 端口扫描 nmap -sC -sV 10.129.205.1422 测试思路 目标服务器只开启了80端口,所以出发点从80端口开始。对于web页面,能做的大致思路有: 1.目录扫描   2…

干货下载丨不分业态、不关注核心需求,怎么做得好项目管理?!

项目管理:装备制造业的破局利刃 对于装备制造行业而言,每一笔订单都是非标定制、小批量制造。这种特性决定了其行业企业普遍存在新品开发周期长、生产效率低、质量不稳定、交货期不稳定、成本预算难控制、非标品报价慢等问题。 如何提升企业的管理水平…

【Java JVM】实例对象的创建

当我们涉及 Java 编程时, 对象的创建是一个基础而关键的概念。在 Java 中, 一切皆为对象, 而对象的创建方式直接影响代码的结构和性能。 本博客将探讨一下 Java 实例对象的创建过程。 1 创建对象的方法有哪些 在 Java 中如果要创建一个对象, 有哪些方式呢? 运用 new 关键字创…

国产or进口?台阶仪为何要选择国产

在微观轮廓测量领域,选择一款合适的台阶仪对于获得精准的测量结果至关重要。随着科技的不断发展,台阶仪市场上涌现了许多国产和进口产品,消费者在选择时可能会面临一些疑虑。 什么是台阶仪 台阶仪是一种超精密接触式微观轮廓测量仪&#xf…

JavaWeb文件上传与下载

一.文件上传 1. 引入两个jar包 jar包可以在maven库进行下载,地址:https://mvnrepository.com,一般点击下载量最多的jar进行下载就可以了。 apache:commons-fileupload.jarcommons-fileupload.jar这个jar包是依赖commons-io.jar的 2. 代码 前端代码&…

桌面概率长按键盘无法连续输入问题

问题描述:概率性长按键盘无法连续输入文本 问题定位: 系统按键流程分析 图一 系统按键流程 按键是由X Server接收的,这一点只要明白了X Window的工作机制就不难理解了。X Server在接收到按键后,会转发到相应程序的窗口中。在窗…

重启docker容器后,ssh无法访问且浏览器无法访问

今天把云服务器中的docker容器重启一遍后,发现里面的项目访问不到了,而且也无法ssh访问。 改了一天,终于还是改好了。 一 .首先是无法ssh访问, 我无法ssh连接的原因是因为我容器的重启之后sshd没有了,然后重新下载了…

助力智能人群检测计数,基于YOLOv5全系列模型【n/s/m/l/x】开发构建通用场景下人群检测计数识别系统

在一些人流量比较大的场合,或者是一些特殊时刻、时段、节假日等特殊时期下,密切关注当前系统所承载的人流量是十分必要的,对于超出系统负荷容量的情况做到及时预警对于管理团队来说是保障人员安全的重要手段,本文的主要目的是想要…

SpringIOC之作用域Scope

博主介绍:✌全网粉丝5W+,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验✌ 博主作品:《Java项目案例》主要基于SpringBoot+MyBatis/MyBatis-plus+…

设计模式之创建型设计模式(一):单例模式 原型模式

单例模式 Singleton 1、什么是单例模式 在软件设计中,单例模式是一种创建型设计模式,其主要目的是确保一个类只有一个实例,并提供一个全局访问点。 这意味着无论何时需要该类的实例,都可以获得相同的实例,而不会创建…

使用VBA快速统计词组词频(多单词组合)(2/2)

实例需求:产品清单如A列所示,现在如下统计多单词组合词组词频。 在上一篇博客中《使用VBA快速统计词组词频(多单词组合)(1/2)》讲解了如何实现双词的词频统计。 本文将讲解如何实现3词的词频统计,掌握实现方法之后&a…

前端Vue必问面试题

1,Vue3.0 为什么要使用 proxy 在 Vue2 中, 0bject.defineProperty 会改变原始数据,而 Proxy 是创建对象的虚拟表示,并提供 set 、get 和 deleteProperty 等处理器,这些处理器可在访问或修改原始对象上的属性时进行拦截,有以下特点∶ 不需用使用 Vue. s e t 或 V u e . s…

硬件编程语言

硬件画板说白了就是电气的连接,相较于PCB连接在2.5D中完成(有些大佬们是直接3D设计)考虑的东西会更多,原理图的抽象使得硬件思路更加简单。 就算是这样, 增加到上千门器件后的大工程是非常难以进行的编辑和检查的&…

Mac如何安装stable diffusion

今天跟大家一起在Mac电脑上安装下stable diffusion,在midjourney等模型收费的情况下如何用自己的电脑算力用上免费的画图大模型呢?来吧一起实操起来 一、安装homebrew 官网地址:Homebrew — The Missing Package Manager for macOS (or Lin…

认识Trino

认识Trino 一、Trino二、结构三、集群四、coordinator五、Worker六、数据源七、连接器八、目录九、架构十、表十一、查询执行模型十二、陈述十三、查询十四、阶段十五、任务十六、分隔十七、Driver十八、Operator十九、Exchange 一、Trino Trino(前身为PrestoSQL&a…

conda和pip配置国内镜像源

1、conda配置镜像源: 使用conda进行安装时,访问的是国外的网络,所以下载和安装包时会特别慢。我们需要更换到国内镜像源地址,这里我更换到国内的清华大学地址。(永久添加镜像) Windows和Linux 对于conda修…

SQL进阶理论篇(十):数据库中的锁

文章目录 简介按照锁的粒度进行划分从数据库管理的角度进行划分从程序员的角度进行划分为什么共享锁会发生死锁?参考文献 简介 索引和锁,是数据库中的两个核心知识点。 索引的相关知识点,在之前的几章里我们已经介绍的差不多了。接下来我们…

[pasecactf_2019]flask_ssti proc ssti config

其实这个很简单 Linux的/proc/self/学习-CSDN博客 首先ssti 直接fenjing一把锁了 这里被加密后 存储在 config中了 然后我们去config中查看即可 {{config}} 可以获取到flag的值 -M7\x10wd94\x02!-\x0eL\x0c;\x07(DKO\r\x17!2R4\x02\rO\x0bsT#-\x1cZ\x1dG然后就可以写代码解…

MNIST内置手写数字数据集的实现

torchvision库 torchivision库是PyTorch中用来处理图像和视频的一个辅助库,接下来我们就会使用torchvision库加载内置的数据集进行分类模型的演示 为了统一数据加载和处理代码,PyTorch提供了两个类用于处理数据加载,他们分别是torch.utils.…

leetcode:641. 设计循环双端队列

设计循环双端队列 实现 MyCircularDeque 类: MyCircularDeque(int k) :构造函数,双端队列最大为 k 。 boolean insertFront():将一个元素添加到双端队列头部。 如果操作成功返回 true ,否则返回 false 。 boolean insertLast() :…