当前位置: 首页 > news >正文

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

在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;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}@Overrideprotected 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;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", money=" + m.money +'}';}@Overrideprotected 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;@Overrideprotected 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;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", money=" + m.money +'}';}@Overrideprotected Object clone() throws CloneNotSupportedException {Student tmp=(Student)super.clone();//克隆了Student里面的值tmp.m= (Money) this.m.clone();//克隆moneyreturn 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.总结

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

 

 

 

 

 

 

 

 

 

 

 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 深度学习-序列模型
  • GoldenEye-v1(vulnhub)靶机练习实践报告
  • windows11 system进程CPU占比过高解决方案
  • 鸿蒙应用开发之OpenGL应用和X组件8
  • 大字体学生出勤记录系统网页源码
  • 打破传统界限,数字沙盘演绎乡村魅力!
  • AI助力科研:自动化科学构思生成系统初探
  • 消费增值:国家支持的消费新零售模型
  • PID控制中积分项目的理解,消除稳态误差的作用,表示着过去(PID积分控制)
  • vue3主题切换按钮与功能实现
  • 海外大带宽云服务器有哪些优势
  • XML和JSON的区别
  • 基于SpringBoot+Vue在线动漫信息平台设计和实现(源码+LW+部署讲解)
  • 【Pandas】深入解析`pd.read_pickle()`函数
  • python常用镜像
  • Android开发 - 掌握ConstraintLayout(四)创建基本约束
  • CSS 提示工具(Tooltip)
  • C语言笔记(第一章:C语言编程)
  • EventListener原理
  • extract-text-webpack-plugin用法
  • HTTP中的ETag在移动客户端的应用
  • js学习笔记
  • LeetCode541. Reverse String II -- 按步长反转字符串
  • React的组件模式
  • use Google search engine
  • windows下mongoDB的环境配置
  • zookeeper系列(七)实战分布式命名服务
  • 悄悄地说一个bug
  • 1.Ext JS 建立web开发工程
  • ​Linux·i2c驱动架构​
  • (day18) leetcode 204.计数质数
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (三)mysql_MYSQL(三)
  • (一)为什么要选择C++
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .NET CORE 第一节 创建基本的 asp.net core
  • .NET Standard 的管理策略
  • .NET 反射 Reflect
  • .net 简单实现MD5
  • .net 重复调用webservice_Java RMI 远程调用详解,优劣势说明
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:Bluetooth组件
  • .NET程序集编辑器/调试器 dnSpy 使用介绍
  • .net快速开发框架源码分享
  • @html.ActionLink的几种参数格式
  • @RequestBody的使用
  • [ linux ] linux 命令英文全称及解释
  • []Telit UC864E 拨号上网
  • [12] 使用 CUDA 加速排序算法
  • [android] 看博客学习hashCode()和equals()
  • [C/C++] -- 二叉树
  • [CakePHP] 在Controller中使用Helper
  • [ESP32] 编码旋钮驱动
  • [HTML]HTML5实现可编辑表格