深拷贝与浅拷贝的那些事儿

Python结合海康威视工业相机SDK实现高效图像采集与处理 本文详细介绍了如何使用Python结合海康威视工业相机SDK实现高效的图像采集与处理。内容涵盖从环境搭建、SDK核心模块理解,到完整的图像采集流程拆解,包括设备枚举、参数设置、主动取流以及关键的像素格式转换。同时,文章深入探讨了触发模式、参数控制等高级应用,并提供了性能优化建议和可复用的相机操作类封装,帮助开发者快速构建稳定的机器视觉应用。 阅读详情

在Java语言里,当我们需要拷贝一个对象时,有两种类型的拷贝:浅拷贝与深拷贝。浅拷贝只是拷贝了源对象的地址,所以源对象的值发生变化时,拷贝对象的值也会发生变化。而深拷贝则是拷贝了源对象的所有值,所以即使源对象的值发生变化时,拷贝对象的值也不会改变。如下图描述:

在这里插入图片描述

了解了浅拷贝和深拷贝的区别之后,本篇博客将教大家几种深拷贝的方法。

拷贝对象

首先,我们定义一下需要拷贝的简单对象。

/**
 * 用户
 */
public class User {
 
    private String name;
    private Address address;
 
    // constructors, getters and setters
 
}
 
/**
 * 地址
 */
public class Address {
 
    private String city;
    private String country;
 
    // constructors, getters and setters
 
}

如上述代码,我们定义了一个User用户类,包含name姓名,和address地址,其中address并不是字符串,而是另一个Address类,包含country国家和city城市。构造方法和成员变量的get()、set()方法此处我们省略不写。接下来我们将详细描述如何深拷贝User对象。

方法一 构造函数

我们可以通过在调用构造函数进行深拷贝,形参如果是基本类型和字符串则直接赋值,如果是对象则重新new一个。
测试用例

@Test
public void constructorCopy() {
 
    Address address = new Address("杭州", "中国");
    User user = new User("大山", address);
 
    // 调用构造函数时进行深拷贝
    User copyUser = new User(user.getName(), new Address(address.getCity(), address.getCountry()));
 
    // 修改源对象的值
    user.getAddress().setCity("深圳");
 
    // 检查两个对象的值不同
    assertNotSame(user.getAddress().getCity(), copyUser.getAddress().getCity());
 
}

方法二 重载clone()方法

Object父类有个clone()的拷贝方法,不过它是protected类型的,我们需要重写它并修改为public类型。除此之外,子类还需要实现Cloneable接口来告诉JVM这个类是可以拷贝的。
重写代码
让我们修改一下User类,Address类,实现Cloneable接口,使其支持深拷贝。

/**
 * 地址
 */
public class Address implements Cloneable {
 
    private String city;
    private String country;
 
    // constructors, getters and setters
 
    @Override
    public Address clone() throws CloneNotSupportedException {
        return (Address) super.clone();
    }
 
}


/**
 * 用户
 */
public class User implements Cloneable {
 
    private String name;
    private Address address;
 
    // constructors, getters and setters
 
    @Override
    public User clone() throws CloneNotSupportedException {
        User user = (User) super.clone();
        user.setAddress(this.address.clone());
        return user;
    }
 
}

需要注意的是,super.clone()其实是浅拷贝,所以在重写User类的clone()方法时,address对象需要调用address.clone()重新赋值。

测试用例
@Test
public void cloneCopy() throws CloneNotSupportedException {
 
    Address address = new Address("杭州", "中国");
    User user = new User("大山", address);
 
    // 调用clone()方法进行深拷贝
    User copyUser = user.clone();
 
    // 修改源对象的值
    user.getAddress().setCity("深圳");
 
    // 检查两个对象的值不同
    assertNotSame(user.getAddress().getCity(), copyUser.getAddress().getCity());
 
}

方法三 Apache Commons Lang序列化

Java提供了序列化的能力,我们可以先将源对象进行序列化,再反序列化生成拷贝对象。但是,使用序列化的前提是拷贝的类(包括其成员变量)需要实现Serializable接口。Apache Commons Lang包对Java序列化进行了封装,我们可以直接使用它。
重写代码
让我们修改一下User类,Address类,实现Serializable接口,使其支持序列化。

/**
 * 地址
 */
public class Address implements Serializable {
 
    private String city;
    private String country;
 
    // constructors, getters and setters
 
}


/**
 * 用户
 */
public class User implements Serializable {
 
    private String name;
    private Address address;
 
    // constructors, getters and setters
 
}
测试用例
@Test
public void serializableCopy() {
 
    Address address = new Address("杭州", "中国");
    User user = new User("大山", address);
 
    // 使用Apache Commons Lang序列化进行深拷贝
    User copyUser = (User) SerializationUtils.clone(user);
 
    // 修改源对象的值
    user.getAddress().setCity("深圳");
 
    // 检查两个对象的值不同
    assertNotSame(user.getAddress().getCity(), copyUser.getAddress().getCity());
 
}

方法四 Gson序列化

Gson可以将对象序列化成JSON,也可以将JSON反序列化成对象,所以我们可以用它进行深拷贝。

测试用例
@Test
public void gsonCopy() {
 
    Address address = new Address("杭州", "中国");
    User user = new User("大山", address);
 
    // 使用Gson序列化进行深拷贝
    Gson gson = new Gson();
    User copyUser = gson.fromJson(gson.toJson(user), User.class);
 
    // 修改源对象的值
    user.getAddress().setCity("深圳");
 
    // 检查两个对象的值不同
    assertNotSame(user.getAddress().getCity(), copyUser.getAddress().getCity());
 
}

方法五 Jackson序列化

Jackson与Gson相似,可以将对象序列化成JSON,明显不同的地方是拷贝的类(包括其成员变量)需要有默认的无参构造函数。
重写代码
让我们修改一下User类,Address类,实现默认的无参构造函数,使其支持Jackson。

/**
 * 用户
 */
public class User {
 
    private String name;
    private Address address;
 
    // constructors, getters and setters
 
    public User() {
    }
 
}


/**
 * 地址
 */
public class Address {
 
    private String city;
    private String country;
 
    // constructors, getters and setters
 
    public Address() {
    }
 
}
测试用例
@Test
public void jacksonCopy() throws IOException {
 
    Address address = new Address("杭州", "中国");
    User user = new User("大山", address);
 
    // 使用Jackson序列化进行深拷贝
    ObjectMapper objectMapper = new ObjectMapper();
    User copyUser = objectMapper.readValue(objectMapper.writeValueAsString(user), User.class);
 
    // 修改源对象的值
    user.getAddress().setCity("深圳");
 
    // 检查两个对象的值不同
    assertNotSame(user.getAddress().getCity(), copyUser.getAddress().getCity());
 
}

总结

说了这么多深拷贝的实现方法,哪一种方法才是最好的呢?最简单的判断就是根据拷贝的类(包括其成员变量)是否提供了深拷贝的构造函数、是否实现了Cloneable接口、是否实现了Serializable接口、是否实现了默认的无参构造函数来进行选择。如果需要详细的考虑,则可以参考下面的表格:

在这里插入图片描述

2024年12月中国电子学会青少年软件编程(Python)等级考试试卷(五级)答案 + 解析 阅读详情

相关推荐

从零开始学版图(二)-----------差分放大电路

从零开始学版图

m0_56112720的博客 8562

实现对象深拷贝的五种方法

对象深拷贝的五种方法 1.json暴力转化 通过JSON.stringify() 和 JSON.parse() 将对象转为字符串之后在转为对象。 var obj = {name:'123'} var obj2 = JSON.parse(JSON.stringify(obj 这种简单粗暴的方式有局限性,当值为undefined、function、symbol会在转换过程中被忽略。 2 es6解构赋 var obj = {name:'123',age:13}; var obj2 = {...obj} 只能深

a88480的博客 2万+

vscode中创建vue快捷键

1.安装Vetur插件(扩展里面直接搜) 2.vscode 界面里面左上角选则 文件=> 首选项=> 用户代码片段=>新建全局代码片段=>在输入框中新建名称为vue.json 3.删除里面的注释,当然你也可以留着,把下面的代码粘贴进去! { // Place your 全局 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and // descri

Leon_940002463的博客 3207

对象深拷贝的5种方法

1.使用JSON.parse()结合JSON.stringify()此方法是对上面第4种方法的改进,确保可以深拷贝目标对象中的对象。3.ES6中的Object.assign()方法。4.利用for in 循环遍历原对象。可以将对象中的对象进行深拷贝。5.使用循环+递归方式实现。2.ES6中的扩展运算符。只能深拷贝第一层元素。只能深拷贝第一层元素。只能深拷贝第一层元素。

weixin_42307739的博客 1190

《童虎学习笔记》5分钟用Keepalived搭建MySQL高可用实现虚ip自动漂移

1

tonghu_note的博客 5618

AWSIM模拟器 新增多相机

本文介绍了基于Unity6引擎对AWSIM自动驾驶模拟器的优化方案,主要针对多相机系统的扩展实现。作者通过修改EgoVehicle.cs和AutowareSimulationDemo.cs核心代码,将原单相机系统升级为5相机配置。关键技术点包括:1)使用List容器管理多个CameraSensor组件;2)完善相机初始化流程;3)配置5个相机UI显示窗口;4)修改ROS话题设置。优化后的系统可支持BEVFusion等多传感器融合算法的测试验证,为Autoware.universe 0.45.0及以上版本提供

W805698955的博客 831

深拷贝的五种实现方式

深拷贝的几种实现方式

Z_J_优快云的博客 3万+

基于STM32的智能快递柜设计(全部资料)

本文设计了一种基于STM32F407ZGT6的智能快递柜系统,通过模块化硬件设计和软件算法优化,实现了24小时无人值守、温湿度智能调控、远程监控等功能。系统集成OLED显示、GSM通信、舵机控制、超声波检测等模块,存取响应时间≤3秒,识别准确率达99.2%,较传统模式效率提升60%。测试表明系统运行稳定,用户满意度达92%,具有成本低、安全性高、可扩展性强等特点,为智慧物流末端配送提供了创新解决方案。未来可引入AI算法、太阳能供电等功能进一步优化系统性能。

3254968421的博客 588

有关实现深拷贝的四种方法

深拷贝与浅拷贝: 在开始之前我们需要先了解一下什么是浅拷贝和深拷贝,其实深拷贝和浅拷贝都是针对的引用类型,JS中的变量类型分为值类型(基本类型)和引用类型;对值类型进行复制操作会对值进行一份拷贝,而对引用类型赋值,则会进行地址的拷贝,最终两个变量指向同一份数据。 // 基本类型 var a = 1; var b = a; a = 2; console.log(a, b); // 2, 1 ,a b指向不同的数据 // 引用类型指向同一份数据 var a = {c: 1

张先森的博客 5506

简谈基于FPGA的千兆以太网设计

简谈基于FPGA的千兆以太网设计 今天给大侠带来简谈基于FPGA的千兆以太网设计,话不多说,上货。 今天我们来简单的聊一聊以太网,以太网在FPGA学习中属于比较高级的内容了,有些大侠肯定会感觉以太网学习起来非常不容易。其实,我可以告诉大家,前期学习的基础打扎实了,后期的学习也没那么难。总之就是说难没那么难,说容易也不是那么容易。那么,言归正传,下面让我们一起来聊一聊以太网的学习。 说起以太网,大家可能就会想到百兆以太网、千兆以太网以及万兆以太网等等。局域以太网从10M开始发展,经历几多的变迁,发展到现

3621

PyQt 随笔:信号与槽的两种使用方法:@pyqtSlot 和 connect

在 PyQt 中,信号与槽是实现事件驱动的一种重要机制。通过信号与槽的连接,可以实现对象之间的通信,例如在用户界面中响应按钮点击事件或者数据的变化等。PyQt 提供了两种主要的方法来创建信号与槽的连接:@pyqtSlot 装饰器和 connect 方法。本文将详细介绍这两种方法,并提供相应的源代码示例。在上面的示例中,我们定义了一个名为。

QasdCpp的博客 763

实现对象深拷贝的方法

浅拷贝:将原对象或者原数组的引用直接赋给新对象、新数组,新对象、新数组只是原对象的一个引用,只是复制了一份 深拷贝:会把对象属性的对象和数组也拷贝一份,不会影响原来的对象 假设我们需要复制一个对象,如果不对其进行深拷贝,那么改变其中一个对象后,另一个对象也会跟着改变,实现对象深拷贝有如下方法 1、利用JSON类(就是将一个对象转为JSON字符串,再转回JSON对象) 优点:方便快捷,性能相对比较好 缺点:复杂的对象进行JSON转换时有可能会丢失属性 2、使用递归的方式实现深拷贝 ..

MQJ 1539

RK3568平台开发系列讲解(项目篇)手写数字识别

📢 本篇章带大家基于飞桨(PaddlePaddle),完成一个简单的手写数字识别任务。

内核笔记 1182

关于浅拷贝深拷贝那些事儿

浅拷贝:拷贝的只是对象的(引用)地址,新旧对象还是共享同一块内存,修改新对象会影响到原始对象数值发生变化 深拷贝:完全复制一个对象出来,新旧对象不共享内存,修改新对象不会改变原对象...

会一点点前端 739

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

深拷贝和浅拷贝的那些事儿

浅拷贝和深拷贝

weixin_46602241的博客 123

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

【JavaSE】Cloneable?关于深拷贝与浅拷贝那些事儿咱们一次聊明白

什么是深拷贝,什么是浅拷贝?Java中又该如何实现对象的拷贝呢?这篇文章,深浅拷贝区别与实现一次给你聊明白!

黄小黄的博客 720

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

聊一聊web前端那些事儿,关于深拷贝和浅拷贝

深拷贝和浅拷贝是经常在面试中会出现的,主要考察你对基本类型和引用类型的理解深度。我在无数次的面试中,应聘者还没有一个人能把这个问题回答情况,包括很多机构的培训老师。这篇文章会让你把基本类型和引用类型的区别搞得清清楚楚,搞清楚这两者的区别,你对任何编程语言的都不怕,因为,这不是js一门语言,是任何编程语言中都需要掌握的知识,而且,在任何编程语言中,两者都是一样的。 深拷贝和浅拷贝主要是...

IT教育任姐姐的博客 199

iOS开发那些事儿(五)Objective-C浅拷贝与深拷贝

浅拷贝:copy操作出来的对象指针直接指向模板的地址。即两个对象公用一块内存地址 1 #import <Foundation/Foundation.h> 2 int main(int argc, const char * argv[]) { 3 @autoreleasepool { 4 NSString * testStr ...

HB8889的博客 167

【点杀iOS】深拷贝&浅拷贝&copy的那些事儿

什么是深拷贝?什么是浅拷贝? 为什么经常看到字符串属性要这样定义,那个copy是神马意思? @property(nonatomic,copy)NSString* name; 为什么下面的写法是错误的? @property(nonatomic,copy)NSMutableString* name; copyWithZone方法又到底是干嘛用的? 接下来,我们将...

weixin_34075268的博客 88

关于数据对象浅拷贝和深拷贝的那些事儿!

浅层拷贝 该类型拷贝针对引用类型的数据类型(如数组和对象),拷贝的地址,改变其中一个数据内容,另一个数据的内容也会改变。 eg. 1.直接进行数组和对象的赋值拷贝; 2.对对象中有数组或对象的键进行拷贝(该例子中通过键名拷贝键值。name键的值是字符类型,所以是深拷贝。而剩余两个因为值数组和对象,所以是浅拷贝) //定义一个对象 var obj = { name:“zs”, teg: [“数据结构...

weixin_45103372的博客 495

【Java】小老弟,别再被Java深拷贝浅拷贝绕晕啦

本文以代码和图解形式剖析 Java 对象深拷贝与浅拷贝。浅拷贝复制基本类型属性值,引用类型仅复制引用,新原对象引用属性指向同一地址;深拷贝对引用类型也递归创建新对象,指向不同地址。

JavaDog程序狗 1418

5张图彻底理解Python中的浅拷贝与深拷贝_如何理解python的浅拷贝和深拷贝(3)

① 2000多本Python电子书(主流和经典的书籍应该都有了)② Python标准库资料(最全中文版)③ 项目源码(四五十个有趣且经典的练手项目及源码)④ Python基础入门、爬虫、web开发、大数据分析方面的视频(适合小白学习)⑤ Python学习路线图(告别不入流的学习)输出结果发现没有,赋值就是对物体进行贴标签操作,作用于同一物体。而浅拷贝则会创建一个新的对象,至于对象中的元素,它依然会引用原来的物体,我们再来看一段例子输出如下。

2401_84572413的博客 1072

JS中的深拷贝和浅拷贝区别图解

深浅拷贝 深浅拷贝这个东西是十分基础的,它涉及到了堆栈的问题,如果想要理解深浅拷贝的区别,首先要明白堆和栈的区别。 所以我们先来说一说堆和栈的区别: 堆和栈你可以当成计算机内存中的两个不同的大盒子,不同的数据类型放在不同的盒子里。 我们都知道数据类型分为两种:简单数据类型和复杂数据类型。复杂数据类型就是数组、对象、函数这三个,其他的就是简单数据类型。简单数据类型呢就是放在栈中,复杂数据类型的内容放...

m0_46387873的博客 431

深度解读Python深拷贝与浅拷贝问题_结合程序分析python列表浅拷贝与深拷贝(1)

① 2000多本Python电子书(主流和经典的书籍应该都有了)② Python标准库资料(最全中文版)③ 项目源码(四五十个有趣且经典的练手项目及源码)④ Python基础入门、爬虫、web开发、大数据分析方面的视频(适合小白学习)⑤ Python学习路线图(告别不入流的学习)数据拷贝会涉及到Python中这3个概念,先来看看这几个概念,只有明白了他们才能更好的理解深拷贝与浅拷贝到底是怎么一回事。在Python中,对对象有一种很通俗的说法,万物皆对象。

m0_61408947的博客 854

Python变量赋值的隐秘世界深入解析浅拷贝与深拷贝的内存机制

本文深入探讨Python中变量赋值的底层机制,重点解析浅拷贝与深拷贝的核心区别。通过详细的内存地址分析和代码示例,揭示Python对象在内存中的真实行为。文章从基础赋值操作开始,逐步深入到可变对象与不可变对象的拷贝差异,最后通过实际应用场景展示如何正确选择拷贝方式。无论你是Python初学者还是有一定经验的开发者,都能从中获得对Python内存管理的深刻理解。

ztt123654的博客 841

JavaScript 引用数据类型的浅拷贝和深拷贝

作为一名前端工作者,传递数据是我们最常见不过的操作。所以,这篇我整理了原来的学习笔记,在此做一个 ‘ 深拷贝和浅拷贝 ’ 的总结;在上方法之前,我们需要知道几个概念: 1,数据类型是什么玩意儿? 数据类型,说白了就是对数据按照某种规则(呵,我不知道)打上不同的分类标签。这样做的目的首先是方便 ‘ 程序工程狮’ 方便逻辑进展和纠错;其次是在计算机分配内存的时候,按照不同的类型分配空间,避免了内存的浪费; 基本数据类型:也称为 ‘ 简单数据类型 ’ ,JavaScript的...

weixin_39166851的博客 459
上一篇: Java并发编程之java.util.concurrent包——Semaphore篇
下一篇: 分布式事务解决方案
_Romeo
_Romeo 优质创作者: 后端开发技术领域 优质创作者: 后端开发技术领域
博客等级 码龄8年 2万+粉丝 104原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Romeo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值