当前位置: 首页 > news >正文

Java 浅拷贝会带来的问题

Java 浅拷贝会带来的问题

一,常见问题

Java 中的浅拷贝是指在对象拷贝时,只复制对象的引用,而不是对象本身。这意味着浅拷贝会导致多个对象共享同一块内存空间,当一个对象修改共享内存时,其他对象也会受到影响。
在这里插入图片描述

下面是几个可能出现的问题:

  1. 对象状态被改变:如果一个对象被多个其他对象引用,当其中一个对象改变了该对象的状态,其他对象也会受到影响。这会导致程序的行为不可预测,并且很难调试。

  2. 安全问题:如果一个对象包含敏感信息,例如密码或银行账户信息,如果多个对象共享同一块内存,则其他对象可以轻松地访问这些信息,这会导致安全问题。

  3. 性能问题:如果对象拥有大量的属性和方法,则浅拷贝会在内存中创建多个指向同一对象的引用,这会导致内存占用过高,从而影响程序的性能。

因此,在设计 Java 程序时,应该谨慎使用浅拷贝,并尽可能使用深拷贝来避免以上问题。深拷贝是指在对象拷贝时,复制对象的所有属性和方法,从而创建一个新的对象,使得每个对象都拥有自己的内存空间,不会相互影响。

二,浅拷贝会带来的问题示例代码

以下是三种浅拷贝可能带来的问题的示例代码:

  1. 对象状态被改变:
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 属性。在浅拷贝过程中,person1person2 共享同一个 hobbies 对象。当我们修改其中一个对象的 hobbies 列表时,另一个对象的 hobbies 列表也会被修改,导致对象状态被改变。

  1. 安全问题:
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 类,其中包含账户号码和余额信息。在浅拷贝过程中,account1account2 共享同一个 BankAccount 对象。如果其中一个对象修改了账户余额,另一个对象也会受到影响。这可能导致安全问题,例如,如果账户余额是敏感信息,其他对象可以轻松地访问和修改它。

  1. 性能问题:
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 的整数数组。在浅拷贝过程中,obj1obj2 共享同一个整数数组对象,这可能导致性能问题。当我们修改 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 浅拷贝会带来的问题 一&#xff0c;常见问题 Java 中的浅拷贝是指在对象拷贝时&#xff0c;只复制对象的引用&#xff0c;而不是对象本身。这意味着浅拷贝会导致多个对象共享同一块内存空间&#xff0c;当一个对象修改共享内存时&#xff0c;其他对象也会受到影响。 下…...

Monocle 3 | 太牛了!单细胞必学R包!~(二)(寻找marker及注释细胞)

1写在前面 昨天又是不睡觉的一天&#xff0c;晚上还被家属讲了一通&#xff0c;理由是我去急诊了&#xff0c;没有在办公室待着&#xff0c;他老公疼没人去看。&#x1fae0; 我的解释是只有我一个值班医生&#xff0c;不可能那么及时&#xff0c;而且也不是什么急症啊。&#…...

简述JVM

文章目录 JVM简介JVM运行时数据区堆(线程共享)方法区/元空间/元数据区(线程共享)栈程序计数器 JVM类加载类加载过程双亲委派模型 垃圾回收机制(GC)判断对象是否为垃圾判断是否被引用指向 如何清理垃圾, 释放对象? JVM简介 JVM 是 Java Virtual Machine 的简称, 意为Java虚拟机…...

【多线程面试题 六】、 如何实现线程同步?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a; 如何实现线程同步&…...

地面文物古迹保护方案,用科技为文物古迹撑起“智慧伞”

一、行业背景 当前&#xff0c;文物保护单位的安防系统现状存在各种管理弊端&#xff0c;安防系统没有统一的平台&#xff0c;系统功能不足、建设标准不同&#xff0c;产品和技术多样&#xff0c;导致各系统独立&#xff0c;无法联动&#xff0c;形成了“信息孤岛”。地面文物…...

k8s之Flannel网络插件安装提示forbidden无权限

一、问题描述 在安装k8s的网络插件时&#xff0c;提示如下信息&#xff0c;各种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 是一个轻量、可靠的移动端组件库&#xff0c;于 2017 年开源。 目前 Vant 官方提供了 Vue 2 版本、Vue 3 版本和微信小程序版本&#xff0c;并由社区团队维护 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、打开终端&#xff0c;在根目录下执行npm run build进行打包&#xff0c;打包成功后会生成dist npm run…...

面试题收集——Java基础部分(一)

1、一个".java"源文件中是否可以包括多个类&#xff08;不是内部类&#xff09;&#xff1f;有什么限制&#xff1f;   可以有多个类&#xff0c;但只能有一个public的类&#xff0c;并且public的类名必须与文件名相一致。 2、Java有没有goto?   java中的保留字…...

Vue中this指向问题

文章目录 1 由Vue管理的函数2 不被Vue管理的函数3 总结 1 由Vue管理的函数 computed 计算属性watch 监视属性filters (Vue3中已弃用且不再支持) 过滤器methods 上述属性里配置的函数this指向Vue实例&#xff0c;不要采用箭头函数写法&#xff0c;因为箭头函数没有自己的this对…...

【iPad已停用】解锁教程

iPad多次输错密码时&#xff0c;会自动锁定并停用&#xff0c;这时候你可以使用iTuens或Tenorshare进行解锁。 一、使用iTunes解锁 下载并安装iTunes 使用数据线将iPad连接上电脑 让iPad进入恢复模式&#xff0c;同时安装iPad电源键和Home键&#xff0c;直到Logo出现也不要松…...

python不调用heapq库 实现大顶堆,小顶堆

参考了博客&#xff0c;并对其进行了堆的push() 和 降序排序的补充 【精选】图解堆排序及其Python实现_python 实现小顶堆-CSDN博客 目录 大顶堆 调用结果展示&#xff1a; 小顶堆&#xff1a; 调用结果展示&#xff1a; 此结果与调用heapq库中的heapify(arr)函数等效 …...

STM32F4X SDIO(二) SDIO协议

上一节简单介绍了SD卡的分类&#xff0c;本节将会介绍SD卡的通信协议&#xff0c;也就是SDIO协议。 STM32F4X SDIO&#xff08;二&#xff09;SDIO协议 SD 卡管脚和寄存器SD卡管脚分布SD卡通信协议SD卡寄存器SD卡内部结构 SDIO总线SDIO总线拓扑SDIO总线协议SDIO协议的基本结构…...

设计模式--7个原则

单一职责原则&#xff1a;一个类负责一项职责。 里氏替换原则&#xff1a;继承与派生的规则。 依赖倒置原则&#xff1a;高层模块不应该依赖基层模块&#xff0c;二者都应该依赖其抽象&#xff1b;抽象不应该依赖细节&#xff1b;细节应该依赖抽象。即针对接口编程&#xff0…...

AltiumDesigner原理图编译错误报告信息解释

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、ViolationsAssociated with Buses 有关总线电⽓错误的各类型&#xff08;共 12 项&#xff09;二、ViolationsAssociated Components 有关元件符号电⽓错误…...

使用 Visual Studio Code 编写 TypeScript程序

安装 TypeScript 首先&#xff0c;确保你已经安装了 TypeScript&#xff0c;如果没有安装&#xff0c;请参考https://blog.csdn.net/David_house/article/details/134077973?spm1001.2014.3001.5502进行安装 创建 新建一个文件夹&#xff0c;用vs code打开&#xff0c;在文…...

科大讯飞发布讯飞星火 3.0;开源AI的现状

&#x1f680; 科大讯飞发布讯飞星火 3.0&#xff0c;综合能力超越ChatGPT&#xff08;非GPT-4版&#xff09; 摘要&#xff1a;科大讯飞在2023全球1024开发者节上宣布讯飞星火 3.0正式发布&#xff0c;号称综合能力已超越ChatGPT。据介绍&#xff0c;星火认知大模型 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&#xff0c;并且配置一下git相关信息&#xff0c;可以使用小乌龟来操作代码。也有一些常规git使用方法。 需要的资源 Git-2.42.0-64-bit.exe&#xff08;这个是git代码管理工具&…...

toon boom harmony基础

以下都是tbh快捷键使用&#xff0c;或者一些常用功能介绍 1、在节点视图中&#xff0c;按回车可直接弹出节点库搜索框 2、中心线编辑器 只能编辑用笔刷画出来的线条&#xff0c;铅笔画出来的线条无法编辑。 3、镜头标记 1 右键箭头方向&#xff0c;可弹出下拉&#xff0c;&am…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...