Java---Cloneable接口---浅克隆和深克隆

news2024/11/17 23:34:42

在Java中,我们如何实现一个对象的克隆呢?

在Java中实现对象的克隆,我们要用到Cloneable接口克隆也分为浅克隆和深克隆

1.实现浅克隆

1.重写clone方法

d7029197d72b4326a24eb326f8ff93d4.png

当我们想直接通过前面已经建立好的对象来调用Object类中的clone方法时,发现不行。因为Object类中的clone方法是被protected修饰的,只能在子类的内部调用。如下图

52f74750b2834c678556bf5425424031.png

所以我们要在Student类中重写Object类中的clone方法。 

 在Student类中重写了clone方法如下图所示

cc43cf3b6c3c4a758d16b445eea5bce3.png

重写之后,我们发现就能调用clone方法了。 

0e980672cdba4705a3427542dec92543.png

 

调用之后还会报错。

7c735760428c46a0a44c838c8ea8e978.png

 原因如下图

a4bf5a87cf764f66a2c25f26b54a796e.png

838c1819b1944936b5327213faeb054d.png

 

我们发现clone方法的返回值类型为Object类型,所以我们要进行强制类型转换。

d8fb0e29f78449c08a07c868bd8a1827.png

 

我们发现还会报出以下错 

b128956288d84cb691a05dcf6c7d2a2b.png

 解决方法

在main函数后加下图红色方框里面的字段。

b2f3b5ad4a65486eb92416387c74ff8c.png

到这一步浅克隆就完成了。

1.完整代码

class Student implements Cloneable{
    public String name;
    public int age;
    public Student(String name,int age){
        this.name=name;
        this.age=age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Test {
    public static void main(String[] args)throws CloneNotSupportedException {
        Student student=new Student("张三",18);
        Student student1=(Student) student.clone();
        System.out.println(student);
        System.out.println(student1);
    }
}

运行代码

9331d21ff37a4861a68f421013d077e4.png

发现克隆成功了。

2.浅克隆堆栈图

b355d1dd62614391b1daddfa66568d9d.png

2.实现深克隆

先来看以下代码

class Money{
    double money=24;
}
class Student implements Cloneable{
    public String name;
    public int age;
    Money m=new Money();
    public Student(String name,int age){
        this.name=name;
        this.age=age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", money=" + m.money +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Test {
    public static void main(String[] args)throws CloneNotSupportedException {
        Student student=new Student("张三",18);
        Student student1=(Student) student.clone();
        System.out.println(student);
        System.out.println(student1);
        student1.m.money=8;
    }
}

money一开始的值是24,但是我们将student1的money的值改变为8时,student的money的值也会变为24,因为上面代码只实现了浅克隆,没有实现深克隆。

上面的堆栈图如下

9ab29fb06c334a4286679084780b3924.png

由于m的值都是克隆过来的,所以两个引用都指向一个money,修改了一个money的值,自然会影响两个的m指向的值。

想解决这个问题,我们直接克隆一份money就行了。如下面的堆栈图所示。

81a0140356874b09acf3919ba7aae961.png

代码实现

class Money implements Cloneable{
    double money=24;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Student implements Cloneable{
    public String name;
    public int age;
    Money m=new Money();
    public Student(String name,int age){
        this.name=name;
        this.age=age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", money=" + m.money +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Student tmp=(Student)super.clone();//克隆了Student里面的值
        tmp.m= (Money) this.m.clone();//克隆money
        return tmp;
    }
}
public class Test {
    public static void main(String[] args)throws CloneNotSupportedException {
        Student student=new Student("张三",18);
        Student student1=(Student) student.clone();
        System.out.println(student);
        System.out.println(student1);
        student1.m.money=8;
        System.out.println("修改student1的money的值后");
        System.out.println(student);
        System.out.println(student1);
    }
}

运行代码

b424d494f4974dee894e235505439e92.png

到这里深克隆就实现了。

3.总结

浅克隆克隆的是值,深克隆克隆的是引用。 

 

 

 

 

 

 

 

 

 

 

 

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

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

相关文章

vbs执行报错vbs没有文件拓展,双击无法打开

如果看不到文件扩展名需要设置: 无法双击打开vbs 一般为注册表问题 解决办法 将下方代码保存为xxx.reg Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\.VBS] "VBSFile" [HKEY_CLASSES_ROOT.VBS\PersistentHandler] "{5e941d80-bf96-…

VBA让按钮消失

要求 用VBA搞小程序,有个录入数据的按钮,点击后进行录入数据的操作,操作完成后这个按钮就是灰的,点不动,这个怎么做? 实现过程 没找到让按钮变灰的方法,退而求其次,让按钮消失。 …

linux部署运维1——centos7.9离线安装部署web或java项目所需的依赖环境,包括mysql8.0,nginx1.20,redis5.0等工具

在实际项目部署运维过程中,如果是云服务器,基本安装项目所需的依赖环境都是通过yum联网拉取网络资源实现自动化安装的;但是对于一些特殊场合,在没有外部网络的情况下,就无法使用yum命令联网操作,只能通过编…

Kunpeng Pro测评使用报告

1. 概述 前段时间,收到两条CSDN的短信,邀请我参加Kunpeng Pro的测评活动。说起来,自己玩过的开发板已经不在少数,而自己作为半导体行业的从业者,手上开发过的芯片也有十几款,小到Arm Cortex-A53&#xff0…

北美互联网裁员太狠了,程序员“做管理上岸”越来越难

北美互联网现在裁员太狠了,“做管理上岸”这种事情在现在这种行业形势已经基本不存在了,这个人管理40人的团队该裁还是裁。 然而硅谷还是中国程序员心中的圣地(华子一定程度上也是很多人的心之所向,技术大厂捞人,前后…

Excel计算两个日期之间差额天数及DATEDIF使用

一.计算两个日期之间的差额天数 1.两个日期直接相减就可以得到两个日期间隔的天数,这里需要注意日期格式哦 日期格式需要为XXXX/XX/XX,不能为XXXX.XX.XX,否则显示Value错误如下。 二.使用DATEDIF函数计算差额天数 该函数只能手写,好像不能自…

应对意外断电:气膜建筑的安全防护与智能管理—轻空间

气膜建筑以其独特的结构和高效的建设方式,广泛应用于各类场馆、仓储设施和临时展馆。然而,当遇到意外断电导致气膜内部无法送风时,如何避免气膜倒塌,确保建筑安全呢? 断电应急响应 气膜建筑配备了先进的智能控制系统&a…

从GIMPLE到RTL

从GIMPLE到RTL 从GIMPLE到RTLGIMPLE序列测试代码:CFG如下所示: 一些典型数据结构RTL生成的基本过程变量展开计算当前函数堆栈(Stack Frame)的初始状态变量展开的初始化对可以展开的变量进行展开操作,生成该变量对应的R…

day17

第一题 本题可以采用快速排序的思想,适应随机数指定和三指针划分数组为三个区域的思想: 其中指针的移动细节如上题故事,如下所示: 当a区域的商都大于k时,我们要查找的k位置元素就在左区域,我们进一步在左区…

适合源代码的加密系统

在信息化高度发展的今天,源代码的安全问题日益受到重视。源代码是企业或组织的核心资产,一旦泄露或被篡改,将会对其造成巨大的经济损失和声誉风险。因此,如何有效防止源代码的泄露和算改成为了企业和组织急需解决的问题。沙盒技术…

Git时光机、Git标签、Git分支、GitHub协作

Git时光机(切换版本) 1.查看提交历史 HEAD指针指向这次分支的最后一次提交 版本信息一行显示【git log --prettyoneline】 2.引用日志【git reflog】 (只在自己的工作区中存在) 非常重要:当HEAD指针进行切换之后&…

有类似注册表编辑器的vb6源码吗?vba注册表编辑器

第一步是要实现注册表功能的读写,所有数据类型,枚举列出所有子项 第二步,树形控件之类显示,可视化修改,查看 第三步,导入导出注册表 第四步,注册表监控,检测哪些注册表项是新建、删除…

【Flutter】交错动画自定义动画Hero动画

🔥 本文由 程序喵正在路上 原创,CSDN首发! 💖 系列专栏:Flutter学习 🌠 首发时间:2024年5月29日 🦋 欢迎关注🖱点赞👍收藏🌟留言🐾 目…

北京大学第一医院与智源研究院共同发布基于可信执行环境的AI医学影像挑战赛

肾动脉狭窄是导致继发性高血压及肾功能不全的常见原因,而目前针对肾动脉狭窄功能学的评估尚处于探索阶段。数据保护和可信计算环境是目前人工智能技术应用于临床研究的一大瓶颈。北京大学第一医院与北京智源人工智能研究院心脏AI 联合研究中心特发布基于可信执行环境…

wps表格样式【笔记】

wps表格样式【笔记】 前言版权推荐wps表格样式第一种方法第二种方法 最后 前言 2024-5-15 19:25:47 以下内容源自《【笔记】》 仅供学习交流使用 版权 禁止其他平台发布时删除以下此话 本文首次发布于CSDN平台 作者是CSDN日星月云 博客主页是https://jsss-1.blog.csdn.net …

【第五节】C++的多态性与虚函数

目录 前言 一、子类型 二、静态联编和动态联编 三、虚函数 四、纯虚函数和抽象类 五、虚析构函数 六、重载,重定义与重写的异同 前言 面向对象程序设计语言的三大核心特性是封装性、继承性和多态性。封装性奠定了基础,继承性是实现代码重用和扩展…

JWT身份验证相关安全问题

前言:工作中需要基于框架开发一个贴近实际的应用,找到一款比较合适的cms框架,其中正好用到的就是jwt做身份信息验证,也记录一下学习jwt相关的安全问题过程。 JWT介绍 Json web token (JWT), 是为了在网络应用环境间传递声明而执行…

如何遍历并处理不平衡的Python数据集

目录 一、引言 二、不平衡数据集的概念与影响 三、处理不平衡数据集的策略 重采样策略 集成学习方法 代价敏感学习 一分类方法 四、Python工具与库 五、案例分析与代码实现 案例一:使用imbalanced-learn库进行上采样 案例二:使用scikit-learn…

知识付费小程序源码系统 界面支持万能DIY装修,一站式运营 附带完整的源代码以及搭建教程

系统概述 这是一款功能强大的知识付费小程序源码系统,它为用户提供了一个全面的平台,能够满足各种知识付费场景的需求。其界面支持万能 DIY 装修,让用户可以根据自己的品牌形象和风格进行个性化定制,打造出独具特色的小程序界面。…

台灯护眼是真的吗?台灯怎么选对眼睛好?看这一篇就够了

随着现代生活方式的改变,孩子们面临着越来越多的视力挑战。我们一直使用普通台灯,往往忽略了不合适的台灯也会给孩子眼部健康带来危害。普通台灯,尤其是使用白炽灯或荧光灯作为光源的台灯,会发射出紫外线。这些紫外线辐射对孩子的…