浅克隆与深克隆

news2024/9/27 15:32:04

1、浅克隆

1.1、什么是浅克隆?

        被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然

        指向原来的对象(克隆对象与原型对象共享引用数据类型变量)。

        如下图所示:

                

1.2、浅克隆代码实现

         类实现接口 Cloneable,表示该类的对象是可以克隆的

         示例代码1:

public class ConcretePrototype implements Cloneable {

    public ConcretePrototype() {
        System.out.println("具体的对象创建完成!");
    }

    @Override
    protected ConcretePrototype clone() throws CloneNotSupportedException {
        System.out.println("具体的对象复制成功!");
        return (ConcretePrototype)super.clone();
    }
}

      测试

@Test
    public void test01() throws CloneNotSupportedException {
        ConcretePrototype c1 = new ConcretePrototype();
        ConcretePrototype c2 = c1.clone();

        System.out.println("对象c1和c2是同一个对象?" + (c1 == c2));
    }

      打印结果:

             对象c1和c2是同一个对象?true

      示例代码2:

            在 类 ConcretePrototype 中添加一个引用类型的属性Person,如下所示:

public class ConcretePrototype implements Cloneable {

    private Person person;

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    void show(){
        System.out.println("嫌疑人姓名: " +person.getName());
    }

    public ConcretePrototype() {
        System.out.println("具体的对象创建完成!");
    }

    @Override
    protected ConcretePrototype clone() throws CloneNotSupportedException {
        System.out.println("具体的对象复制成功!");
        return (ConcretePrototype)super.clone();
    }

}

public class Person {

    private String name;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

      测试:

@Test
    public void test02() throws CloneNotSupportedException {
        ConcretePrototype c1 = new ConcretePrototype();
        Person p1 = new Person();
        c1.setPerson(p1);

        //复制c1
        ConcretePrototype c2 = c1.clone();
        //获取复制对象c2中的Person对象
        Person p2 = c2.getPerson();
        p2.setName("慕容复");

        //判断p1与p2是否是同一对象
        System.out.println("p1和p2是同一个对象?" + (p1 == p2));

        c1.show();
        c2.show();
    }

     打印结果:

            p1和p2是同一个对象?true
            嫌疑人姓名:慕容复
            嫌疑人姓名:慕容复

     p1与p2是同一对象,这是浅克隆的效果,也就是对具体原型类中的引用数据类型的属性进行

     引用的复制

2、深克隆

2.1、什么是深克隆

         除去那些引用其他对象的变量,被复制对象的所有变量都含有与原来的对象相同的值。那些

         引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言

          之,深复制把要复制的对象所引用的对象都复制了一遍。如下图所示:

                

2.2、深克隆代码实现

         对于上边浅克隆示例2中的代码,如果有需求场景中不允许共享同一对象,那么就需要使用

         “深拷贝”,如果想要进行深拷贝需要使用到对象序列化流 (对象序列化之后,再进行反序列化

          获取到的是不同对象)。代码如下

@Test
    public void test03() throws Exception {

        ConcretePrototype c1 = new ConcretePrototype();
        Person p1 = new Person("峰哥");
        c1.setPerson(p1);

        //创建对象序列化输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("c.txt"));

        //将c1对象写到文件中
        oos.writeObject(c1);
        oos.close();

        //创建对象序列化输入流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("c.txt"));

        //读取对象
        ConcretePrototype c2 = (ConcretePrototype) ois.readObject();
        Person p2 = c2.getPerson();
        p2.setName("凡哥");

        //判断p1与p2是否是同一个对象
        System.out.println("p1和p2是同一个对象?" + (p1 == p2));

        c1.show();
        c2.show();
    }

3、总结

     1)Java中的Object类中提供了 `clone()` 方法来实现“浅克隆”。需要注意的是要想实现克隆

           的Java类必须实现一个标识接口 Cloneable ,来表示这个Java类支持被复制。

     2)其实现在不推荐大家用Cloneable接口,实现比较麻烦,现在借助Apache Commons或

          者springframework可以直接实现:
              (1)浅克隆:BeanUtils.cloneBean(Object obj);

                                      BeanUtils.copyProperties(S,T);
              (2)深克隆:SerializationUtils.clone(T object);
          BeanUtils是利用反射原理获得所有类可见的属性和方法,然后复制到target类。
          SerializationUtils.clone()就是使用我们的前面讲的序列化实现深克隆,当然你要把要克隆

          的类实现Serialization接口。

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

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

相关文章

教育在线答题在线小程序源码系统 PHP+MySQL组合开发源码开源可二次开发 带搭建部署教程

系统概述 教育在线答题在线小程序源码系统是一款专为教育行业设计的,集在线题库管理、智能组卷、在线答题、自动评分、成绩分析等功能于一体的综合性平台。该系统采用PHP作为后端开发语言,结合MySQL数据库进行数据存储与管理,确保了系统的稳…

数据在内存中的存储(下)

目录 前言一、浮点数在内存中的存储1.1 练习1.2 浮点数的存储1.2.1 浮点数存的过程1.2.2 浮点数取的过程 1.3 题目解析 总结 前言 前面一期我们主要说到整形在数据中的存储方式,这期我们来看看浮点数在内存中是如何存储的,话不多说,正文开始…

Proto3 深度解读:Protobuf 的用法与实例分析(C++)

文章目录 1. 前言1.1 序列化和反序列化1.2 什么情况下要进行序列化1.3 部分序列化工具 2. 了解Protobuf2.1 什么是Protobuf2.2 proto 成分2.3 如何编译proto2.4 编译.proto文件后生成的文件都有什么? 3. Protobuf的使用3.1 Protobuf的使用过程3.2 上手编写实例 4. p…

打印沙漏(最蠢的办法)

直接给代码&#xff0c;很好理解的 #include<bits/stdc.h> using namespace std; int s(int b){if(b<1)return 0;if(b2)return 1;for(int i3;i<sqrt(b);i){if(b%i0)return 0;}return 1; } int main(){int n;cin>>n;char c;cin>>c;vector<int>s;…

什么是服务器日志,日志有什么作用?

前言 服务器日志是指服务器等电脑设备或软件的运作记录‌。这些日志记录了服务器接收客户端处理请求的过程以及服务器对这些请求的处理结果。服务器日志对于排查和解决计算机系统和网络应用中的问题至关重要&#xff0c;因为它们包含了用于调试问题的消息、服务器状态以及其他…

深入解析网络通信关键要素:IP 协议、DNS 及相关技术

我的主页&#xff1a;2的n次方_ 1. IP 协议报头结构 4 位版本&#xff1a;表示 IPv4 / IPv6 4 位首部长度&#xff1a;表示 IP 报头的长度&#xff0c;以 4 字节为单位 8 位服务类型&#xff1a;包括 3 位优先权字段&#xff08;已弃用&#xff09;&#xff0c;4 位 TOS 字…

css基础知识(二)

“落座无言行三载&#xff0c;持笔无悔笑苍生&#xff01;” 文章目录 前言文章有误敬请斧正 不胜感恩&#xff01;1. 选择器类型标签选择器类选择器ID选择器通配符选择器复合选择器 2. 元素显示模式块级元素行内元素行内块元素 3. 背景属性4. 字体和文本属性5.垂直居中的实现方…

vue到出excel

安装 npm install exceljs npm install file-saver<template><button click"dade66">导出 66</button> </template><script> import ExcelJS from exceljs; import { saveAs } from file-saver;export default {data() {return {data…

Unity多语言插件I2 Localization国际化应用

【就不收费了&#xff0c;要个关注不过分吧】 【图片来自插件官网&#xff0c;侵删】 前言 目前游戏往往都不会仅局限于国内语言&#xff0c;为了适应产品都要做国际化适配&#xff0c;因此会用到这个插件&#xff0c;这个插件要付费&#xff0c;因此请前往unity官网进行下载…

Windows系统设置定时任务,周期性执行.bat文件

通过.bat清除注册表项 在 Windows 系统中&#xff0c;.bat 文件&#xff08;批处理文件&#xff09;是一个包含一系列命令的文本文件。这些命令会被 Windows 命令解释器 (cmd.exe) 依次执行。 你可以把它想象成一个简单的程序&#xff0c;但它不像 C 或 Python 那样需要编译&a…

Go容器化微服务系统实战

1-1 本课的go微服务有什么不同&#xff1f; 聚焦于容器化可观测的购物微服务系统实战&#xff0c;通过介绍Go语言的应用趋势、容器化优势及微服务适用性&#xff0c;旨在解决学习微服务过程中遇到的难点。课程内容涵盖微服务整体架构、技术工具框架及容器平台等关键技术&#…

Linux文件IO(九)-原子操作与竞争冒险

Linux 是一个多任务、多进程操作系统&#xff0c;系统中往往运行着多个不同的进程、任务&#xff0c;多个不同的进程就有可能对同一个文件进行 IO 操作&#xff0c;此时该文件便是它们的共享资源&#xff0c;它们共同操作着同一份文件&#xff1b;操作系统级编程不同于大家以前…

javase复习day33网络编程

网络编程 常见的软件架构 BS架构 CS架构 网络编程小结 网络编程三要素 三要素小结 IP IPV4 IPV6 IP小结 IPV4的地址分类形式 常用的CMD命令 小结 InetAddress的使用 public class Demo1 {public static void main(String[] args) throws UnknownHostException {//获取IP对象/*…

【EI会议大盘点!涵盖计算机图像视觉、机器学习等众多方向】

EI会议&#xff0c;作为全球知名的学术会议平台&#xff0c;以其广泛的影响力和严格的收录标准著称。 相较于SCI、核心期刊等期刊来说&#xff0c;EI会议的审稿周期更短&#xff0c;最快7天即可录用。 费用上也相对较低&#xff0c;这对于资金和时间双重压力的学生党来说&…

Rpc框架——服务端框架设计

目录 一、Network 二、Protocol 三、Dispatcher 四、RpcRouter 五、Publish-Subscribe 六、Registry-Discovery 七、Server 服务端的功能需求&#xff1a; 基于网络通信接收客户端的请求&#xff0c;提供rpc服务 基于网络通信接收客户端的请求&#xff0c;提供服务注…

【POJ-1061 青蛙的约会】

题目 代码 #include <bits/stdc.h> using namespace std; typedef long long LL; LL ex_gcd(LL a, LL b, LL &x, LL &y) {if (b 0){x 1;y 0;return a;}LL gcd ex_gcd(b, a % b, x, y);LL tmp x;x y;y tmp - a / b * y;return gcd; } int main() {LL x, y…

springboot实战学习(9)(配置mybatis“驼峰命名“和“下划线命名“自动转换)(postman接口测试统一添加请求头)(获取用户详细信息接口)

接着学习。之前的博客的进度&#xff1a;完成用户模块的注册接口的开发以及注册时的参数合法性校验、也基本完成用户模块的登录接口的主逻辑的基础上、JWT令牌"的组成与使用以及完成了"登录认证"&#xff08;生成与验证JWT令牌&#xff09;具体往回看了解的链接…

SpringBoot项目编译运行成功,但有些包名类名仍然下划线标红的解决方法 | Idea

目录 问题解决方案&#xff1a;方法一&#xff1a;方法二【我用这个成功的】 问题 如图&#xff0c;成功运行但有些包名类名仍然下划线标红&#xff0c;强迫症抓狂 成功运行&#xff1a; 有些包导入标红&#xff1a; 解决方案&#xff1a; 方法一&#xff1a; 点击fil…

K8S介绍---搭建集群

Kubernetes介绍 官网&#xff1a;https://kubernetes.io/ 一、应用部署方式演变 1、传统部署&#xff1a;互联网早期&#xff0c;会直接将应用程序部署在物理机上 优点&#xff1a;简单&#xff0c;不需要其他技术的参与 缺点&#xff1a;不能为应用程序定义资源使用边界&a…

AXI4-Stream

AXI4-Stream 简介信号握手机制字节类型TKEEP和TSTRBAXI4-Stream Data FIFO正常模式packet模式 AXI4-Stream Interconnect 简介 这是一种连续流接口&#xff0c;不需要地址线&#xff08;很像 FIFO &#xff0c;一直读或一直写就行&#xff09;。对于这类 IP &#xff0c;ARM 不…