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

java 深拷贝 浅拷贝 详解

在 Java 中,深拷贝浅拷贝是对象拷贝(复制)时的两个重要概念,它们决定了拷贝后的对象与原对象之间的关联性。以下是深拷贝和浅拷贝的详解,包括定义、实现方式及其区别。


1. 概念解释

1.1 浅拷贝(Shallow Copy)

浅拷贝是对对象的一种表层复制

  • 基本数据类型的字段会复制其值。
  • 引用数据类型的字段会复制其引用地址(即引用同一个对象)。

拷贝后的对象与原对象共享引用类型的成员。

特性

  • 拷贝对象与原对象的引用类型字段指向同一个内存地址。
  • 修改引用类型的内容会影响到原对象。

1.2 深拷贝(Deep Copy)

深拷贝是对对象的一种完全复制

  • 基本数据类型的字段会复制其值。
  • 引用数据类型的字段会递归拷贝新对象,即创建新的内存空间,拷贝后不共享引用。

拷贝后的对象与原对象完全独立。

特性

  • 拷贝对象与原对象互不影响,任何修改只会影响对应对象。

2. 示例代码

2.1 浅拷贝示例

使用 Object.clone() 方法实现浅拷贝:

class Person implements Cloneable {String name;Address address;Person(String name, Address address) {this.name = name;this.address = address;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone(); // 调用 Object 的 clone 方法}
}class Address {String city;Address(String city) {this.city = city;}
}public class ShallowCopyExample {public static void main(String[] args) throws CloneNotSupportedException {Address address = new Address("New York");Person person1 = new Person("John", address);// 浅拷贝Person person2 = (Person) person1.clone();// 修改拷贝对象的引用类型字段person2.address.city = "Los Angeles";// 原对象的引用类型字段也被修改System.out.println(person1.address.city); // 输出:Los Angeles}
}

2.2 深拷贝示例

手动实现深拷贝:

class Person implements Cloneable {String name;Address address;Person(String name, Address address) {this.name = name;this.address = address;}@Overrideprotected Object clone() throws CloneNotSupportedException {// 创建一个浅拷贝Person clonedPerson = (Person) super.clone();// 手动深拷贝引用类型字段clonedPerson.address = new Address(this.address.city);return clonedPerson;}
}class Address {String city;Address(String city) {this.city = city;}
}public class DeepCopyExample {public static void main(String[] args) throws CloneNotSupportedException {Address address = new Address("New York");Person person1 = new Person("John", address);// 深拷贝Person person2 = (Person) person1.clone();// 修改拷贝对象的引用类型字段person2.address.city = "Los Angeles";// 原对象的引用类型字段未被修改System.out.println(person1.address.city); // 输出:New York}
}

3. 区别对比

特性浅拷贝深拷贝
拷贝方式仅复制对象的基本类型字段和引用类型字段的引用地址。复制对象的所有字段,包括引用类型字段所指向的对象。
内存分配原对象和拷贝对象共享引用类型字段的内存地址。原对象和拷贝对象完全独立,占用不同的内存空间。
修改影响修改拷贝对象的引用类型字段会影响原对象。修改拷贝对象不会影响原对象。
实现复杂度简单,可以直接使用 Object.clone() 方法。较复杂,需要手动实现递归拷贝。
适用场景引用类型字段无需独立,或对性能要求高的场景。引用类型字段需要独立且完全隔离的场景。

4. 实现深拷贝的常用方式

4.1 使用 clone() 方法

  • 递归实现拷贝每个引用类型字段。
  • 需要确保所有类都实现 Cloneable 接口,并重写 clone() 方法。

4.2 使用序列化

通过将对象序列化为字节流再反序列化来实现深拷贝:

import java.io.*;class Person implements Serializable {String name;Address address;Person(String name, Address address) {this.name = name;this.address = address;}
}class Address implements Serializable {String city;Address(String city) {this.city = city;}
}public class DeepCopyWithSerialization {public static void main(String[] args) throws IOException, ClassNotFoundException {Address address = new Address("New York");Person person1 = new Person("John", address);// 深拷贝Person person2 = deepCopy(person1);// 修改拷贝对象的引用类型字段person2.address.city = "Los Angeles";// 原对象的引用类型字段未被修改System.out.println(person1.address.city); // 输出:New York}// 序列化深拷贝方法private static <T> T deepCopy(T object) throws IOException, ClassNotFoundException {ByteArrayOutputStream byteOut = new ByteArrayOutputStream();ObjectOutputStream out = new ObjectOutputStream(byteOut);out.writeObject(object);ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());ObjectInputStream in = new ObjectInputStream(byteIn);return (T) in.readObject();}
}

4.3 使用第三方库

一些第三方库(如 Apache Commons Lang 的 SerializationUtils)可以简化深拷贝的实现。


5. 注意事项

  1. Cloneable 接口的限制

    • 默认的 Object.clone() 方法只能实现浅拷贝,需要手动实现深拷贝。
  2. 性能考虑

    • 深拷贝通常比浅拷贝耗时更多,尤其是引用类型字段复杂时。
  3. 引用循环问题

    • 如果对象内部存在循环引用(即对象引用自身或其他对象),需要特别处理,避免递归拷贝时发生栈溢出。
  4. 使用场景选择

    • 如果引用类型字段无需独立修改,浅拷贝通常已足够。
    • 如果引用类型字段需要独立,且修改后不影响原对象,使用深拷贝。

6. 总结

浅拷贝深拷贝
仅复制值类型字段和引用地址复制值类型字段,并递归复制引用类型字段所指向的对象
性能较高,但存在引用共享的问题性能较低,但保证拷贝对象独立
适用于引用类型字段无需独立修改的场景适用于引用类型字段需要独立且完全隔离的场景

在实际应用中,应根据具体需求选择合适的拷贝方式。浅拷贝适用于简单的场景,而深拷贝更适合复杂对象需要完全隔离的场景。

相关文章:

java 深拷贝 浅拷贝 详解

在 Java 中&#xff0c;深拷贝和浅拷贝是对象拷贝&#xff08;复制&#xff09;时的两个重要概念&#xff0c;它们决定了拷贝后的对象与原对象之间的关联性。以下是深拷贝和浅拷贝的详解&#xff0c;包括定义、实现方式及其区别。 1. 概念解释 1.1 浅拷贝&#xff08;Shallow …...

针对git、giteeVSCode连接的使用 || Live Share插件使用

1.下载git 链接 打开终端&#xff0c;桌面鼠标右键 2.配置密钥 登录gitee。 设置密钥 查看官方文档 跟着教程 复制最后的输出进行密钥添加 验证是否添加成功 3.创建&连接远程仓库 创建仓库 git终端进行配置 远程仓库克隆到本地 桌面终端clone,克隆他人|自己的仓库到本地…...

如何解决Ubuntu 20.04中Vim编辑器在按下Ctrl+S时暂停响应的问题

如何解决Ubuntu 20.04中Vim编辑器在按下CtrlS时暂停响应的问题 在Ubuntu 20.04中使用Vim编辑器时&#xff0c;用户可能会遇到按下CtrlS后编辑器似乎“卡死”或无响应的情况。这个问题实际上源于历史悠久的终端行为&#xff0c;而非Vim本身或操作系统的缺陷。以下是详细的分析及…...

mybatisPlus打印sql配置

MyBatis-Plus 提供了方便的配置方式来打印 SQL 查询语句&#xff0c;以便进行调试和性能分析。可以通过配置 log 来输出 SQL 语句以及执行的参数。 方法 1&#xff1a;通过 application.properties 或 application.yml 配置打印 SQL 可以通过配置 application.properties 或 a…...

Redis 内存管理

参考&#xff1a;面试官&#xff1a;为什么 Redis 不立刻删除已经过期的数据&#xff1f; 目录 1.Redis 给缓存数据设置过期时间有什么用&#xff1f; 2.Redis 是如何判断数据是否过期的呢&#xff1f; 3.Redis 过期 key 删除策略了解么&#xff1f; 4.大量 key 集中过期怎…...

Excel表文本函数、日期和时间函数

一、文本函数 函数说明CHAR返回字符代码所对应的字符CLEAN删除文本中的所有不可打印字符CODE返回文本字符串首字符的代码CONCATENATE合并多个文本字符串EXACT检查两个文本是否完全相同FIND查找文本中某个字符串的位置LEFT从文本的左边开始返回指定数量的字符LEN返回文本字符串…...

从零到一:利用 AI 开发 iOS App 《震感》的编程之旅

在网上看到一篇关于使用AI开发的编程经历&#xff0c;分享给大家 作者是如何在没有 iOS 开发经验的情况下&#xff0c;借助 AI&#xff08;如 Claude 3 模型&#xff09;成功开发并发布《震感》iOS 应用。 正文开始 2022 年 11 月&#xff0c;ChatGPT 诞生并迅速引发全球关注。…...

基于Java Springboot幼儿园管理系统

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据…...

Python小白学习教程从入门到入坑------习题课2(基础巩固)

目录 一、选择题 二、实战题 2.1 实战1&#xff1a;输入一个年份&#xff0c;判断是否是闰年 2.2 实战2&#xff1a;模拟10086查询功能 2.3 实战3&#xff1a;使用嵌套循环输出九九乘法表 2.4 实战4&#xff1a;猜数游戏 一、选择题 1、以下选项符合Python语法要求且能够…...

基于IPMI_SSH的服务器硬件监控指标解读

随着企业IT架构的日益复杂化&#xff0c;对服务器的实时监控和管理变得至关重要。监控易作为一款功能强大的监控软件&#xff0c;支持通过IPMI_SSH的方式对服务器硬件进行远程监控&#xff0c;确保服务器的稳定运行。本文将针对监控易中基于IPMI_SSH的服务器硬件监控指标进行解…...

数据结构-二叉树及其遍历

🚀欢迎来到我的【数据结构】专栏🚀 🙋我是小蜗,一名在职牛马。🐒我的博客主页​​​​​​ ➡️ ➡️ 小蜗向前冲的主页🙏🙏欢迎大家的关注,你们的关注是我创作的最大动力🙏🙏🌍前言 本篇文章咱们聊聊数据结构中的树,准确的说因该是只说一说二叉树以及相…...

(33)iptables设置防火墙策略常用命令(docker环境、非docker环境)

#普通环境&#xff08;非docker&#xff09; # 拒绝所有对端口 31001 的访问 iptables -A INPUT -p tcp --dport 31001 -j DROP # 允许 IP 地址 20.59.30.77 访问端口 31001 (此处用的是虚拟机 所以要使用nat地址的网关) iptables -I INPUT 1 -p tcp -s 20.59.30.77 --dpor…...

fastadmin中动态下拉组件(SelectPage)的使用

实现的功能如下&#xff1a; 1、支持模糊搜索&#xff1b;2、分页功能&#xff1b;3支持多选 官方文档&#xff1a;https://doc.fastadmin.net/doc/178.html html页面引用组件 <div class"form-group"><label class"control-label col-xs-12 col-sm-2…...

通过Python 调整Excel行高、列宽

在Excel中&#xff0c;默认的行高和列宽可能不足以完全显示某些单元格中的内容&#xff0c;特别是当内容较长时。通过调整行高和列宽&#xff0c;可以确保所有数据都能完整显示&#xff0c;避免内容被截断。合理的行高和列宽可以使表格看起来更加整洁和专业&#xff0c;尤其是在…...

力扣-Mysql-3278. 寻找数据科学家职位的候选人 II(中等)

一、题目来源 3278. 寻找数据科学家职位的候选人 II - 力扣&#xff08;LeetCode&#xff09; 二、数据表结构 表&#xff1a;Candidates ----------------------- | Column Name | Type | ----------------------- | candidate_id | int | | skill | varch…...

Android笔记(三十六):封装一个Matrix从顶部/底部对齐的ImageView

背景 ImageView的scaleType默认显示图片是这样&#xff0c;但是有时候设计稿需求希望图片左右能紧贴着ImageView左右边缘&#xff0c;又不破坏图片的比例&#xff0c;用自带的matrix&#xff0c;centerCrop等都可以满足 但是都会造成图片的某些区域被裁剪了&#xff0c;如果设…...

web 入门

学习 Web 开发的基础&#xff0c;建议从以下几个方面入门&#xff0c;按步骤循序渐进学习核心知识&#xff1a; 1. 了解 Web 的基础概念 在开始编码之前&#xff0c;先理解 Web 开发的基本工作原理&#xff1a; Web 前端与后端&#xff1a; 前端&#xff1a;负责用户界面和用…...

京东 2025届秋招 自然语言处理

文章目录 个人情况一面/HR面 10min二面/技术面 1h三面/技术面 1h四面/线下HR面 20min 个人情况 先说一下个人情况&#xff1a; 学校情况&#xff1a;211本中9硕&#xff0c;本硕学校都一般&#xff0c;本硕都是计算机科班&#xff0c;但研究方向并不是NLP&#xff0c;而是图表…...

Mybatis框架之模板方法模式 (Template Method Pattern)

MyBatis 中也使用到了 模板方法模式 (Template Method Pattern)&#xff0c;主要体现在 执行 SQL 语句的流程控制 上。模板方法模式允许 MyBatis 定义数据库操作的标准流程&#xff0c;并允许子类或特定实现类去实现某些步骤。这种模式使得 MyBatis 能够在处理不同类型的 SQL 操…...

【进阶系列】python简单爬虫实例

python有一个很强大的功能就是爬取网页的信息&#xff0c;这里是CNBlogs 网站&#xff0c;我们将以此网站为实例&#xff0c;爬取指定个页面的大标题内容。代码如下&#xff1a; 首先是导入库&#xff1a; # 导入所需的库 import requests # 用于发送HTTP请求 from bs4 impor…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...