Java 浅拷贝会带来的问题
Java 浅拷贝会带来的问题
一,常见问题
Java 中的浅拷贝是指在对象拷贝时,只复制对象的引用,而不是对象本身。这意味着浅拷贝会导致多个对象共享同一块内存空间,当一个对象修改共享内存时,其他对象也会受到影响。

下面是几个可能出现的问题:
-
对象状态被改变:如果一个对象被多个其他对象引用,当其中一个对象改变了该对象的状态,其他对象也会受到影响。这会导致程序的行为不可预测,并且很难调试。
-
安全问题:如果一个对象包含敏感信息,例如密码或银行账户信息,如果多个对象共享同一块内存,则其他对象可以轻松地访问这些信息,这会导致安全问题。
-
性能问题:如果对象拥有大量的属性和方法,则浅拷贝会在内存中创建多个指向同一对象的引用,这会导致内存占用过高,从而影响程序的性能。
因此,在设计 Java 程序时,应该谨慎使用浅拷贝,并尽可能使用深拷贝来避免以上问题。深拷贝是指在对象拷贝时,复制对象的所有属性和方法,从而创建一个新的对象,使得每个对象都拥有自己的内存空间,不会相互影响。
二,浅拷贝会带来的问题示例代码
以下是三种浅拷贝可能带来的问题的示例代码:
- 对象状态被改变:
public class Person implements Cloneable {private String name;private List<String> hobbies;public Person(String name, List<String> hobbies) {this.name = name;this.hobbies = hobbies;}public void setName(String name) {this.name = name;}public void setHobbies(List<String> hobbies) {this.hobbies = hobbies;}public String getName() {return name;}public List<String> getHobbies() {return hobbies;}@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}
}public class ShallowCopyExample {public static void main(String[] args) throws CloneNotSupportedException {List<String> hobbies = new ArrayList<>();hobbies.add("Reading");hobbies.add("Gardening");Person person1 = new Person("Alice", hobbies);Person person2 = (Person) person1.clone();System.out.println("person1: " + person1.getName() + ", Hobbies: " + person1.getHobbies());System.out.println("person2: " + person2.getName() + ", Hobbies: " + person2.getHobbies());person2.getHobbies().add("Cooking");System.out.println("person1: " + person1.getName() + ", Hobbies: " + person1.getHobbies());System.out.println("person2: " + person2.getName() + ", Hobbies: " + person2.getHobbies());}
}
在上面的示例代码中,我们创建了一个 Person 类,其中包含一个 List 类型的 hobbies 属性。在浅拷贝过程中,person1 和 person2 共享同一个 hobbies 对象。当我们修改其中一个对象的 hobbies 列表时,另一个对象的 hobbies 列表也会被修改,导致对象状态被改变。
- 安全问题:
public class BankAccount implements Cloneable {private String accountNumber;private double balance;public BankAccount(String accountNumber, double balance) {this.accountNumber = accountNumber;this.balance = balance;}public void setAccountNumber(String accountNumber) {this.accountNumber = accountNumber;}public void setBalance(double balance) {this.balance = balance;}public String getAccountNumber() {return accountNumber;}public double getBalance() {return balance;}@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}
}public class ShallowCopyExample {public static void main(String[] args) throws CloneNotSupportedException {BankAccount account1 = new BankAccount("123456789", 1000.0);BankAccount account2 = (BankAccount) account1.clone();System.out.println("account1: " + account1.getAccountNumber() + ", Balance: " + account1.getBalance());System.out.println("account2: " + account2.getAccountNumber() + ", Balance: " + account2.getBalance());account2.setBalance(500.0);System.out.println("account1: " + account1.getAccountNumber() + ", Balance: " + account1.getBalance());System.out.println("account2: " + account2.getAccountNumber() + ", Balance: " + account2.getBalance());}
}
在上面的示例代码中,我们创建了一个 BankAccount 类,其中包含账户号码和余额信息。在浅拷贝过程中,account1 和 account2 共享同一个 BankAccount 对象。如果其中一个对象修改了账户余额,另一个对象也会受到影响。这可能导致安全问题,例如,如果账户余额是敏感信息,其他对象可以轻松地访问和修改它。
- 性能问题:
public class LargeObject implements Cloneable {private int[] data;public LargeObject(int[] data) {this.data = data;}public void setData(int[] data) {this.data = data;}public int[] getData() {return data;}@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}
}public class ShallowCopyExample {public static void main(String[] args) throws CloneNotSupportedException {int[] data = new int[1000000];LargeObject obj1 = new LargeObject(data);LargeObject obj2 = (LargeObject) obj1.clone();System.out.println("obj1 data length: " + obj1.getData().length);System.out.println("obj2 data length: " + obj2.getData().length);obj2.getData()[0] = 10;System.out.println("obj1 data length: " + obj1.getData().length);System.out.println("obj2 data length: " + obj2.getData().length);}
}
在上面的示例代码中,我们创建了一个 LargeObject 类,其中包含一个长度为 1000000 的整数数组。在浅拷贝过程中,obj1 和 obj2 共享同一个整数数组对象,这可能导致性能问题。当我们修改 obj2 中的数组元素时,obj1 中的数组元素也会被修改,因为它们指向同一块内存。如果对象拥有大量的属性和方法,浅拷贝会导致内存占用过高,从而影响程序的性能。
三,深拷贝示例代码
以下是一个深拷贝工具类的示例代码,使用了 Java 的序列化和反序列化机制来实现深拷贝:
import java.io.*;public class DeepCopyUtils {public static <T extends Serializable> T deepCopy(T object) throws IOException, ClassNotFoundException {ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(baos);oos.writeObject(object);ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bais);return (T) ois.readObject();}
}
在上面的示例代码中,我们定义了一个泛型 deepCopy 方法,它接受一个实现了 Serializable 接口的对象作为参数,并返回该对象的深拷贝副本。具体实现过程与之前的示例代码相同。
对于实现了接口的对象,我们可以通过以下示例代码进行深拷贝:
public interface Shape extends Serializable {void draw();
}public class Circle implements Shape {private int x;private int y;private int radius;public Circle(int x, int y, int radius) {this.x = x;this.y = y;this.radius = radius;}@Overridepublic void draw() {System.out.println("Drawing Circle at (" + x + ", " + y + "), radius " + radius);}
}public class DeepCopyExample {public static void main(String[] args) throws IOException, ClassNotFoundException {Circle circle1 = new Circle(10, 20, 30);Circle circle2 = DeepCopyUtils.deepCopy(circle1);circle2.draw();}
}
在上面的示例代码中,我们定义了一个 Shape 接口和一个实现了该接口的 Circle 类。在 DeepCopyExample 类中,我们创建了一个 Circle 对象 circle1,并将其深拷贝到 circle2 中。最后,我们调用 circle2.draw() 方法来验证深拷贝是否成功。
需要注意的是,如果被拷贝的对象中包含了不可序列化的成员变量,那么该成员变量也无法被正确地拷贝。此外,对于非常复杂的对象图,深拷贝可能会导致性能问题。 我有更好的拷贝代码工具类有需要可以跟我要
相关文章:
Java 浅拷贝会带来的问题
Java 浅拷贝会带来的问题 一,常见问题 Java 中的浅拷贝是指在对象拷贝时,只复制对象的引用,而不是对象本身。这意味着浅拷贝会导致多个对象共享同一块内存空间,当一个对象修改共享内存时,其他对象也会受到影响。 下…...
Monocle 3 | 太牛了!单细胞必学R包!~(二)(寻找marker及注释细胞)
1写在前面 昨天又是不睡觉的一天,晚上还被家属讲了一通,理由是我去急诊了,没有在办公室待着,他老公疼没人去看。🫠 我的解释是只有我一个值班医生,不可能那么及时,而且也不是什么急症啊。&#…...
简述JVM
文章目录 JVM简介JVM运行时数据区堆(线程共享)方法区/元空间/元数据区(线程共享)栈程序计数器 JVM类加载类加载过程双亲委派模型 垃圾回收机制(GC)判断对象是否为垃圾判断是否被引用指向 如何清理垃圾, 释放对象? JVM简介 JVM 是 Java Virtual Machine 的简称, 意为Java虚拟机…...
【多线程面试题 六】、 如何实现线程同步?
文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享? 踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。 面试官: 如何实现线程同步&…...
地面文物古迹保护方案,用科技为文物古迹撑起“智慧伞”
一、行业背景 当前,文物保护单位的安防系统现状存在各种管理弊端,安防系统没有统一的平台,系统功能不足、建设标准不同,产品和技术多样,导致各系统独立,无法联动,形成了“信息孤岛”。地面文物…...
k8s之Flannel网络插件安装提示forbidden无权限
一、问题描述 在安装k8s的网络插件时,提示如下信息,各种forbidden无权限 [rootzzyk8s01 scripts]# kubectl apply -f kube-flannel.yml Error from server (Forbidden): error when retrieving current configuration of: Resource: "policy/v1b…...
在微信小程序云开发中引入Vant Weapp组件库
介绍 Vant 是一个轻量、可靠的移动端组件库,于 2017 年开源。 目前 Vant 官方提供了 Vue 2 版本、Vue 3 版本和微信小程序版本,并由社区团队维护 React 版本和支付宝小程序版本。 介绍 - Vant Weapp (youzan.github.io) Vant Weapp需要安装 node.js&…...
Vue+ElementUI项目打包部署到Ubuntu服务器中
1、修改config/index.js中的assetsPublicPath: /,修改为assetsPublicPath: ./ assetsPublicPath: ./2、在build/utils.js中增加publicPath: ../../ publicPath: ../../3、打开终端,在根目录下执行npm run build进行打包,打包成功后会生成dist npm run…...
面试题收集——Java基础部分(一)
1、一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致。 2、Java有没有goto? java中的保留字…...
Vue中this指向问题
文章目录 1 由Vue管理的函数2 不被Vue管理的函数3 总结 1 由Vue管理的函数 computed 计算属性watch 监视属性filters (Vue3中已弃用且不再支持) 过滤器methods 上述属性里配置的函数this指向Vue实例,不要采用箭头函数写法,因为箭头函数没有自己的this对…...
【iPad已停用】解锁教程
iPad多次输错密码时,会自动锁定并停用,这时候你可以使用iTuens或Tenorshare进行解锁。 一、使用iTunes解锁 下载并安装iTunes 使用数据线将iPad连接上电脑 让iPad进入恢复模式,同时安装iPad电源键和Home键,直到Logo出现也不要松…...
python不调用heapq库 实现大顶堆,小顶堆
参考了博客,并对其进行了堆的push() 和 降序排序的补充 【精选】图解堆排序及其Python实现_python 实现小顶堆-CSDN博客 目录 大顶堆 调用结果展示: 小顶堆: 调用结果展示: 此结果与调用heapq库中的heapify(arr)函数等效 …...
STM32F4X SDIO(二) SDIO协议
上一节简单介绍了SD卡的分类,本节将会介绍SD卡的通信协议,也就是SDIO协议。 STM32F4X SDIO(二)SDIO协议 SD 卡管脚和寄存器SD卡管脚分布SD卡通信协议SD卡寄存器SD卡内部结构 SDIO总线SDIO总线拓扑SDIO总线协议SDIO协议的基本结构…...
设计模式--7个原则
单一职责原则:一个类负责一项职责。 里氏替换原则:继承与派生的规则。 依赖倒置原则:高层模块不应该依赖基层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。即针对接口编程࿰…...
AltiumDesigner原理图编译错误报告信息解释
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、ViolationsAssociated with Buses 有关总线电⽓错误的各类型(共 12 项)二、ViolationsAssociated Components 有关元件符号电⽓错误…...
使用 Visual Studio Code 编写 TypeScript程序
安装 TypeScript 首先,确保你已经安装了 TypeScript,如果没有安装,请参考https://blog.csdn.net/David_house/article/details/134077973?spm1001.2014.3001.5502进行安装 创建 新建一个文件夹,用vs code打开,在文…...
科大讯飞发布讯飞星火 3.0;开源AI的现状
🚀 科大讯飞发布讯飞星火 3.0,综合能力超越ChatGPT(非GPT-4版) 摘要:科大讯飞在2023全球1024开发者节上宣布讯飞星火 3.0正式发布,号称综合能力已超越ChatGPT。据介绍,星火认知大模型 V3.0在文…...
公网远程访问macOS本地web服务器
# 公网访问macOS本地web服务器【内网穿透】 文章目录 1. 启动Apache服务器2. 公网访问本地web服务2.1 本地安装配置cpolar2.2 创建隧道2.3 测试访问公网地址3. 配置固定二级子域名3.1 保留一个二级子域名3.2 配置二级子域名4. 测试访问公网固定二级子域名 以macOS自带的Apache…...
windows 安装小乌龟
这是什么 这里简单描述一下在windows上如何安装GIT代码管理工具和使用小乌龟版本来调用GIT,并且配置一下git相关信息,可以使用小乌龟来操作代码。也有一些常规git使用方法。 需要的资源 Git-2.42.0-64-bit.exe(这个是git代码管理工具&…...
toon boom harmony基础
以下都是tbh快捷键使用,或者一些常用功能介绍 1、在节点视图中,按回车可直接弹出节点库搜索框 2、中心线编辑器 只能编辑用笔刷画出来的线条,铅笔画出来的线条无法编辑。 3、镜头标记 1 右键箭头方向,可弹出下拉,&am…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...
Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...
《信号与系统》第 6 章 信号与系统的时域和频域特性
目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...
车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...
ZYNQ学习记录FPGA(二)Verilog语言
一、Verilog简介 1.1 HDL(Hardware Description language) 在解释HDL之前,先来了解一下数字系统设计的流程:逻辑设计 -> 电路实现 -> 系统验证。 逻辑设计又称前端,在这个过程中就需要用到HDL,正文…...
