Clonable 接口和深拷贝

Object 类中存在一个 clone 方法, 调用这个方法可以创建一个对象的 “拷贝”.
在这里插入图片描述

想用clone方法时报错了,查看一下:
在这里插入图片描述

  • clone方法被protected修饰.不同包只能在子类中访问,可以用super关键字访问
  • clone方法返回类型是Object,所以需要向下转型
  • CloneNotSupportedException是受查异常,所以调用它的方法不处理就要throws,main方法不处理就交给JVM处理了

改良的代码

class Person {public String name;public Person(String name) {this.name = name;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
public class Test {public static void main(String[] args) throws CloneNotSupportedException {Person person1 = new Person("张三");Person person2 = (Person)person1.clone();System.out.println(person2.name);}
}

但还是会报错
在这里插入图片描述
要想合法调用 clone 方法, 必须先实现 Clonable 接口, 否则就会抛出 CloneNotSupportedException 异常,而它是空的,没有需要重写的方法
在这里插入图片描述
如果一个类实现了这个空接口/标记接口,那么证明当前类是可以被克隆的

class Person implements Cloneable{public String name;public Person(String name) {this.name = name;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
public class Test {public static void main(String[] args) throws CloneNotSupportedException {Person person1 = new Person("张三");Person person2 = (Person)person1.clone();System.out.println(person2.name);}
}

在这里插入图片描述
可以用try-catch进行处理,这样就不必用throws将异常报告给抛出异常方法的调用者

class Person implements Cloneable {public String name;public Person(String name) {this.name = name;}@Overridepublic Person clone() {Person person = null;try {person = (Person) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return person;}
}
public class Test {public static void main(String[] args) {Person person = new Person("张三");Person person2 = person.clone();System.out.println(person2.name);}
}

在这里插入图片描述

浅拷贝和深拷贝

Cloneable 拷贝出的对象是一份 “浅拷贝”

class Money {public double money = 13;
}
class Person implements Cloneable{public String name;public Money m;public Person(String name) {this.name = name;m = new Money();}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
public class Test {public static void main(String[] args) throws CloneNotSupportedException {Person person1 = new Person("张三");Person person2 = (Person)person1.clone();System.out.println("修改之前:"+person1.m.money);System.out.println("修改之前:"+person2.m.money);person2.m.money = 99;System.out.println("修改之后:"+person1.m.money);System.out.println("修改之后:"+person2.m.money);}
}

在这里插入图片描述

我们只修改了person2 的money,但person1的money也被改成了99.

内存分布大致是这样的
假设0x56,0x87指向引用地址的对象

在这里插入图片描述
我们可以看到,通过clone,我们只是拷贝了Person对象。但是Person对象中的Money对象并
没有拷贝。通过person2这个引用修改了m的值后,person1这个引用访问m的时候,值也发生了改变。这里就是发生了浅拷贝
改完后person1和person2还是指向同一个m,因为改变基本数据类型不会创建新的对象.

深拷贝是克隆出一个完全独立于原来对象的对象(如果类中有基本数据类型那就进行拷贝)

代码如下:

class Money implements Cloneable{public double money = 13;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
class Person implements Cloneable{public String name;public Money m;public Person(String name) {this.name = name;m = new Money();}@Overrideprotected Object clone() throws CloneNotSupportedException {Person tmp = (Person) super.clone();tmp.m = (Money)this.m.clone();return tmp;}
}
public class Test {public static void main(String[] args) throws CloneNotSupportedException {Person person1 = new Person("张三");Person person2 = (Person)person1.clone();System.out.println("修改之前:"+person1.m.money);System.out.println("修改之前:"+person2.m.money);person2.m.money = 99;System.out.println("修改之后:"+person1.m.money);System.out.println("修改之后:"+person2.m.money);}
}

在这里插入图片描述
在这里插入图片描述
是不是深拷贝,就看程序猿实现的方式怎么样

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

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

相关文章

FormData文件上传多文件上传

一、简介 ​ 通常情况下,前端在使用post请求提交数据的时候,请求都是采用application/json 或 application/x-www-form-urlencoded编码类型,分别是借助JSON字符串来传递参数或者keyvalue格式字符串(多参数通过&进行连接&#…

React 中的 ref 和 refs:解锁更多可能性(上)

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

算法分析与设计课后练习29

给定集合S{3, 7, 5, 9}, C 20, 近似参数 ε0.2, 写出 近似算法求解子集和问题的过程。

ThinkPad E550c

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:…

喜讯丨思码逸正式加入北京信创工委会!

近日,经北京信息化协会信息技术应用创新工作委员会(以下简称“北京信创工委会”)投票表决,研发效能行业领先者北京思码逸科技有限公司(简称:思码逸)正式加入“北京信创工委会”,成为…

国产670亿参数的DeepSeek:超越Llama2,全面开源

模型概述 DeepSeek,一款国产大型语言模型(LLM),凭借其670亿参数的规模,正引领着人工智能领域的新浪潮。这款模型不仅在多项中英文公开评测榜单上超越了700亿参数的Llama 2,而且在推理、数学和编程能力方面…

计算机网络(3):数据链路层

数据链路层属于计算机网络的低层。 数据链路层使用的信道主要有以下两种类型: (1)点对点信道。这种信道使用一对一的点对点通信方式。 (2)广播信道。这种信道使用一对多的广播通信方式。广播信道上连接的主机很多,因此必须使用专用的共享信道协议来协调这…

Hive入门+部署

看黑马视频做的笔记 目录 概念 1.基本概述 2.基础架构 总架构 部署 1.安装MySQL 2.配置Hadoop 3.下载解压Hive 4.下载MySQL Driver包 注意! 5.配置Hive 6.初始化元数据库 7.启动Hive(使用Hadoop用户) 实例 查看HDFS上表中存…

Axure中继器的基本使用

介绍中继器 在 Axure 中,中继器是一种交互设计元素,用于在不同页面之间传递数据或触发特定的事件。它可以帮助模拟真实的用户交互流程和页面之间的传递逻辑,继承关系用于描述两个元件之间的父子关系。通过使用继承关系,您可以创建…

BBS项目--登录

BBS阶段性测试总要求 django登录报错 Error: [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。 原因分析:出现这种情况在Windows中很常见,就是端口被占用 解决措施:这时我们只需改一下端口便可以了 登录前端页面(HTML…

网络基础介绍

1.网线制作 1.1 网线制作需要的工具 网线 网线钳 水晶头 测试仪 ​编辑 1.2 网线的标准 1.3 网线的做法 2.集线器&交换机&路由器的介绍 3.OSI七层模型 4.路由器的设置 4.1 常见的路由器设置地址 4.2 常见的路由器账号密码 4.3 登录路由器 设置访客网…

Dynamsoft Barcode Reader 使用教程:QR码,PDF417和DataMatrix有什么区别?

Dynamsoft Barcode Reader SDK一款多功能的条码读取控件,只需要几行代码就可以将条码读取功能嵌入到Web或桌面应用程序。这可以节省数月的开发时间和成本。能支持多种图像文件格式以及从摄像机或扫描仪获取的DIB格式。使用Dynamsoft Barcode Reader SDK,…