一篇文章带你了解cloneable接口、浅拷贝、深拷贝

简介: 我们都知道想要实现拷贝需要实现Cloneable接口并在类中实现clone()方法,不过比较神奇的是,clone()方法并不是Cloneable接口中的方法。Cloneable接口是一个空接口,里面没有任何内容

微信搜索《Java鱼仔》,每天一个知识点不错过


每天一个知识点


cloneable接口有什么用,浅拷贝和深拷贝你知道吗?


(一)cloneable接口有什么用


我们都知道想要实现拷贝需要实现Cloneable接口并在类中实现clone()方法,不过比较神奇的是,clone()方法并不是Cloneable接口中的方法。


Cloneable接口是一个空接口,里面没有任何内容


网络异常,图片无法展示
|


但是如果没有实现Cloneable接口,就会导致clone()方法报CloneNotSupportException错误,所以你可以把Cloneable接口看成实现clone()方法必须要的一个因素。


(二)什么是深拷贝和浅拷贝


开发过程中,有时会遇到把现有的一个对象的所有成员属性拷贝给另一个对象的需求。这个时候就会用到拷贝这个概念。我们把原对象定义成A,拷贝后的对象定义成B,如果只是单纯使用clone方法进行拷贝,你会发现:


1、对于八个基本类型,会拷贝其值,并且B的改变不会影响A。


2、如果是一个对象,拷贝的是地址引用,也就是说此时新拷贝出的对象与原有对象共享该实例变量,不受访问权限的限制。B对该值的改变会影响A。


3、对于String字符串,这个比较特殊,虽然拷贝的也是引用,但是在修改的时候,它会从字符串池中重新生成新的字符串,原有的字符串对象保持不变。


这种只单纯拷贝引用地址的动作就是浅拷贝。


相反,如果拷贝一个对象时不是简单的将地址引用拷贝出来,而是新建了一个对象,这种方式就是深拷贝。


(三)浅拷贝代码模拟


通过代码模拟浅拷贝的过程:


首先,新建两个实体类,学生和老师:


publicclassTeacher {
privateintid;
privateStringname;
//省略构造方法、get、set、toString方法}

接下来是学生,学生的实体类需要实现clone

publicclassStudentimplementsCloneable {
privateintid;
privateStringname;
privateTeacherteacher;
//省略构造方法、get、set、toString方法@OverrideprotectedObjectclone() throwsCloneNotSupportedException {
returnsuper.clone();
    }
}


网络异常,图片无法展示
|


通过结果就可以发现,修改被克隆对象的基本类型和String类型不会对原来数据造成影响,但是由于用的是同一个引用地址,修改对象时两边都会被修改。


(四)深拷贝代码模拟


深拷贝的其中一个方法是把被拷贝对象中的所有引用类型也都实现深拷贝,最后逐层拷贝实现引用地址是新的而不是用的同一个。


修改上面的teacher对象代码,实现clone方法


publicclassTeacherimplementsCloneable{
privateintid;
privateStringname;
//省略构造方法、get、set、toString方法@OverrideprotectedObjectclone() throwsCloneNotSupportedException {
returnsuper.clone();
    }
}

修改student类的clone方法

@OverrideprotectedObjectclone() throwsCloneNotSupportedException {
Studentstudent= (Student) super.clone();
student.teacher= (Teacher) teacher.clone();
returnstudent;
}

然后执行同样的测试代码后就会发现两个对象已经互相不影响了。


第二个方法是利用serializable实现深拷贝,这种方式的原理在于通过IO流的方式先将序列化后的对象写进IO流中,再取出来实现深拷贝。这种方式下所有涉及到的类都必须实现Serializable接口


新建一个DeepStudent类


publicclassDeepStudentimplementsSerializable {
privatestaticfinallongserialVersionUID=1L;
privateintid;
privateStringname;
privateTeacherteacher;
//省略构造方法、get、set、toString方法publicObjectdeepCopy(){
try {
//将对象写到IO流中ByteArrayOutputStreambos=newByteArrayOutputStream();
ObjectOutputStreamoos=newObjectOutputStream(bos);
oos.writeObject(this);
//再从IO流中获取到对象ByteArrayInputStreambis=newByteArrayInputStream(bos.toByteArray());
ObjectInputStreamois=newObjectInputStream(bis);
returnois.readObject();
        } catch (IOException|ClassNotFoundExceptione) {
e.printStackTrace();
        }
returnnull;
    }
}

编写一个测试方法:

publicstaticvoidmain(String[] args) throwsCloneNotSupportedException {
//新建一个student1DeepStudentstudent1=newDeepStudent(1,"javayz",newTeacher(1,"teacher1"));
//student2从student1中克隆过去DeepStudentstudent2= (DeepStudent) student1.deepCopy();
//修改基本类型 intstudent2.setId(2);
//修改Stringstudent2.setName("javayz2");
//修改对象类型teacherTeacherteacher=student2.getTeacher();
teacher.setName("teacher2");
System.out.println(student1);
System.out.println(student2);
    }


相关文章
|
存储 自然语言处理 关系型数据库
MySQL高级篇——索引的创建与设计原则
索引的分类与使用、MySQL8.0索引新特性、适合创建索引的情况、不适合创建索引的情况
MySQL高级篇——索引的创建与设计原则
|
安全
SCP文件上传中断的问题
SCP文件上传中断的问题
1955 1
|
Java
Java 清空 List 的多种方法?
Java 清空 List 的多种方法?
2809 0
|
7天前
|
移动开发 JavaScript weex
UniApp开发的App在启动速度方面有哪些优势和劣势?
UniApp开发的App在启动速度方面有哪些优势和劣势?
198 137
|
12月前
|
监控 Kubernetes Python
Python 应用可观测重磅上线:解决 LLM 应用落地的“最后一公里”问题
为增强对 Python 应用,特别是 Python LLM 应用的可观测性,阿里云推出了 Python 探针,旨在解决 LLM 应用落地难、难落地等问题。助力企业落地 LLM。本文将从阿里云 Python 探针的接入步骤、产品能力、兼容性等方面展开介绍。并提供一个简单的 LLM 应用例子,方便测试。
421 130
|
IDE Java 测试技术
IDEA安装并使用通义灵码
本文介绍了“通义灵码”这一智能编码助手的功能特点,并提供了在IDEA中安装和使用的详细步骤,旨在帮助提升编程效率和代码质量。
IDEA安装并使用通义灵码
|
9月前
|
缓存 Linux 数据库
CentOS 8中 更新或下载时报错:为仓库 ‘appstream‘ 下载元数据失败 : Cannot prepare internal
通过以上步骤,您可以有效地解决 CentOS 8 中“为仓库 ‘appstream’ 下载元数据失败 : Cannot prepare internal”问题。关键在于检查网络连接、更新和切换仓库配置、清理缓存、重建 RPM 数据库以及在必要时临时禁用有问题的仓库。通过这些方法,可以确保系统能够正常进行软件包的更新和下载操作。
2581 20
|
消息中间件 存储 Cloud Native
RocketMQ从4.9.7 升级到5.3.0有什么变化?
【8月更文挑战第25天】RocketMQ从4.9.7 升级到5.3.0有什么变化?
820 4
|
存储 分布式计算 DataWorks
dataworks数据集成
dataworks数据集成
461 2
|
监控 Java 开发者
Java面试题:如何使用JVM工具(如jconsole, jstack, jmap)来分析内存使用情况?
Java面试题:如何使用JVM工具(如jconsole, jstack, jmap)来分析内存使用情况?
671 2