一文道破Java中的深拷贝,浅拷贝,零拷贝

news2024/9/27 17:30:54

前言

在Java编写代码中,对象的拷贝是一个常见的操作。根据拷贝的层次和方式不同,可以分为深拷贝、浅拷贝和零拷贝。本篇文章我们将详细介绍这三种拷贝方式的概念、实现方法以及使用场景,方便大佬学习及面试。

在这里插入图片描述

深拷贝

深拷贝是一种创建对象副本的方法,其中新对象与原始对象完全独立。这就意味着新对象的所有字段都被复制,并且如果字段是引用类型,那么递归地执行深拷贝,以确保新对象和原始对象不共享任何内部对象。

如何实现深拷贝呢,接下来介绍一下:

  1. 手动实现:通过创建一个新的对象,并逐个复制字段的值。如果字段是引用类型,需要递归地创建该字段的新实例,只不过这个过程比较繁琐。
  2. 使用序列化:将对象序列化为字节流,然后再反序列化回一个新对象。这种方法要求对象及其所有组成部分都是可序列化的。
  3. 使用克隆:实现Cloneable接口并重写clone()方法。但这种方法有争议,因为它可能不提供真正的深拷贝,除非所有相关的类都正确实现了clone()方法。

举个栗子,我们现在有简单的Person类和一个Address类:

class Address implements Serializable {  
    private String street;  
    // ... 其他属性和方法 ...  
}  
  
class Person implements Serializable {  
    private String name;  
    private Address address;  
    // ... 其他属性和方法 ...  
      
    public Person deepCopy() {  
        try {  
            // 使用序列化实现深拷贝  
            ByteArrayOutputStream baos = new ByteArrayOutputStream();  
            ObjectOutputStream oos = new ObjectOutputStream(baos);  
            oos.writeObject(this);  
            oos.close();  
              
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());  
            ObjectInputStream ois = new ObjectInputStream(bais);  
            return (Person) ois.readObject();  
        } catch (Exception e) {  
            throw new RuntimeException(e);  
        }  
    }  
}

代码解释:
不难看出,Person类有一个Address类型的字段。我们实现Serializable接口了并使用序列化和反序列化技术,可以创建一个Person对象的深拷贝。这就意味着新创建的Person对象和原始对象是完全独立的,它们不共享任何内部状态。

浅拷贝

浅拷贝创建一个新对象,并复制原始对象的所有非静态字段到新对象。但是,如果字段是引用类型,那么只复制引用而不复制引用的对象。因此,对于引用类型的字段,原始对象和新对象共享同一个内部对象。

那么实现浅拷贝呢,方法如下:

我们通常可以通过创建一个新对象,并且使用构造函数或setter方法将原始对象的值复制到新对象中来实现浅拷贝。Java中的自动装箱和拆箱机制可以简化基本数据类型的复制

Such as:

使用上面的Person和Address类为例:

class Person {  
    private String name;  
    private Address address;  
    // ... 其他属性和方法 ...  
      
    public Person shallowCopy() {  
        Person copy = new Person();  
        copy.setName(this.name); // 复制基本数据类型字段  
        copy.setAddress(this.address); // 只复制引用,不复制引用的对象  
        return copy;  
    }  
}

对上面的代码解释一下:
我们创建了一个新的Person对象并且复制基本数据类型字段的值和引用类型字段的引用来实现浅拷贝。这意味着修改新对象的name字段不会影响原始对象,但修改新对象的address字段会影响原始对象,因为它们共享同一个Address对象。

零拷贝

零拷贝是一种在数据传输过程中避免不必要的数据复制的技术。零拷贝通常与I/O操作相关,尤其是当数据从一个存储位置移动到另一个存储位置时。通过直接在内存、文件或网络之间传输数据,零拷贝技术可以减少CPU的使用和内存带宽的消耗,从而提高性能。

Java中什么地方用到了零拷贝技术呢?比如:

  • MappedByteBuffer:使用内存映射文件将文件或文件的一部分映射到内存中,从而允许直接访问文件数据而不需要将数据复制到应用程序的内存中。这可以通过FileChannel中的map()方法实现。
  • FileChannel的transferTo/transferFrom方法:这些方法允许数据直接在文件通道或套接字通道之间传输,而不需要先复制到应用程序的内存中。比如,可以使用FileChannel中的transferTo()方法将数据直接从文件发送到网络套接字。
  • DirectBuffer:通过使用直接缓冲区(DirectBuffer),数据可以直接在操作系统的原生内存中进行处理,而不需要先复制到Java堆内存中。这可以通过创建一个ByteBuffer并调用其allocateDirect()方法来实现。

如,上面就是Java的NIO库提供了一些零拷贝技术的实现方法。

try (FileChannel sourceChannel = new FileInputStream("source.txt").getChannel();  
     FileChannel destinationChannel = new FileOutputStream("destination.txt").getChannel()) {  
    destinationChannel.transferFrom(sourceChannel, 0, sourceChannel.size());  
} catch (IOException e) {  
    e.printStackTrace();  
}

我们在上面的代码中就使用FileChannel的transferFrom()方法实现了文件传输的零拷贝。数据直接从源文件通道传输到目标文件通道,而不需要先复制到应用程序的内存中。这种方法在处理大文件时可以提高性能并减少内存消耗。

文章到这里就先结束了,感兴趣的可以订阅专栏哈,后续会继续分享相关的知识点。

在这里插入图片描述

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

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

相关文章

晶振等效电路工作原理和特性详细解读

晶振等效电路对于理解电子设备的工作原理和故障排除具有重要意义,晶振工作时内部是真实的存在“振动”的,是机械振动。振动的同时两端会输出对应频率的振动电压,这个电压非常精确且稳定,所以我们经常用作时钟信号。 一、等效电路…

【AI】使用阿里云免费服务器搭建Langchain-Chatchat本地知识库

书接上文,由于家境贫寒的原因,导致我本地的GPU资源无法满足搭建Langchain-Chatchat本地知识库的需求,具体可以看一下这篇文章,于是我只能另辟蹊径,考虑一下能不能白嫖一下云服务器资源,于是去找网上找&…

阿里云服务器本地localhost换成本地的IP地址后不能访问的原因

阿里云服务器本地localhost换成本地的IP地址后不能访问的原因 问题在安装以及配置都没有问题的情况下我使用localhost:5001(127.0.0.1:5001)都可以正常使用,但是我是用本机Ip地址的时候发现无法打开网页以上这个问题出现在我阿里云的服务器上…

基于Matlab/Simulink不平衡电网工况下级联H桥光伏并网逆变器仿真模型

本次更新的内容为级联H桥光伏并网逆变器相关的控制,后面会针对储能系统在级联H桥拓扑上的应用进行分享。由于传统发电造成的环境污染问题和光伏电池板价格持续创新低,太阳能从众多种类的可再生能源中拔地而起,因而光伏逆变器成为国内外学者和…

nestjs swagger文档调用需要鉴权的接口

目标 nestjs经常需要设置一些鉴权(登录后)才能访问的接口,但是生成的swagger文档可以发起接口请求,文档发起的请求默认是不携带登录token的,所以需要移除swagger文档发起请求的守卫拦截。 nestjs守卫拦截设置见另一篇…

(Spring学习12)Spring 6.0及SpringBoot 3.0新特性解析

主要内容: 1、GraalVM介绍与基本使用 2、Spring Boot 3.0新特性介绍与实战 3、Docker SpringBoot3.0 新特性实战 4、RuntimeHints介绍与实战 5、Spring AOT作用与核心原理源码分析 GraalVM体验 https://github.com/spring-projects/spring-framework/wiki/What%2…

编解码异常分析

前言 最近在做的项目,有H264解码的需求。部分H264文件解码播放后,显示为绿屏或者花屏。 分析 如何确认是否是高通硬解码的问题 adb 指令 adb root adb remount adb shell setenforce 0 adb shell setprop vendor.gralloc.disable_ubwc 1 adb shell c…

【Unity学习笔记】1.创建场景

创建场景 注1:samplescene(示例场景)、standard assets(标准资产)、favorites(收藏夹)、terrain(地形)。 注2:favorites用于存放各种资源;sample…

【数字图像处理】常见噪声模型选择

1. 引言 1.1 背景介绍 在数字图像处理中,噪声是一个普遍存在的问题,影响图像质量和分析的准确性。本研究旨在深入探讨泊松噪声的参数估计与去噪方法,以提高图像处理的鲁棒性。 1.2 研究目的与意义 通过对各种常见噪声模型的仿真实现&…

计算机视觉基础(12)——图像恢复

前言 我们将学习图像恢复相关知识。主要有图像恢复的定义、评价标准和实现图像恢复的方法。图像恢复任务包括图像去噪、去模糊、图像超分辨率、图像修复等;评价标准有峰值信噪比和结构相似性;图像超分辨的方法有传统方法和基于深度学习的方法&#xff1a…

Python爬虫的作用及工具和反爬机制,爬虫新手入门篇

文章目录 一 什么是爬虫二 爬虫工具三. 反爬虫问题Python爬虫技术资源分享1、Python所有方向的学习路线2、学习软件3、入门学习视频4、实战案例5、清华编程大佬出品《漫画看学Python》6、Python副业兼职与全职路线 一 什么是爬虫 爬虫能做什么 政治角逐 2016年这场美国总统竞…

NC的运行环境 类

NC的运行环境类 package nc.bs.framework.common;import java.io.File; import java.io.IOException; import java.util.Properties; import nc.bs.framework.common.RuntimeEnv.1; import nc.bs.framework.exception.FrameworkRuntimeException; import nc.bs.framework.util…

系列十(实战)、发送 接收批量消息(Java操作RocketMQ)

一、发送 & 接收批量消息 1.1、概述 批量消息是指RocketMQ可以把一组消息集合一次性发送,这一组消息会被当做一个消息供消费者消费。 1.2、Demo05MQTestApp /*** Author : 一叶浮萍归大海* Date: 2023/12/25 11:48* Description: 发送 & 接收批量消息*/ …

修复vscode中prettier格式化失效的问题

vscode中prettier格式化有时会失效,又恢复到编辑器默认格式。 要修复这个问题,可以用 Ctrl Shift P 调出命令面板,然后输入 format 搜索 在出现是搜索结果中选择 Format Document With... 然后选择 Configure Default Formatter 然后选择…

知行之桥EDI系统功能介绍之导入导出配置和嵌入式示例工作流

我们的产品团队正在简化用户使用已配置的 Arc Flows 的过程。我们主要通过两种方式改进了这种体验: 导入/导出配置嵌入式示例流 在本文中,我们将介绍这些新功能,以及它们如何使我们的用户更轻松地使用知行之桥 EDI 系统的工作流。 导入/导…

TomcatHttp协议

1 javaWEB 1.1 Web概述 Web在英文中的含义是网状物,网络。在计算机领域,它通常指的是后者,即网络。像我们前面接触的WWW,它是由3个单词组成的,即:World Wide Web,中文含义是万维网。而我们前…

视觉学习(4) —— 添加地址传递数据

Modbus Slave 选择一个地址右键,选择发送的数据类型 视觉软件 一、添加地址 当地址为100时,先将首地址改为100,第0个地址为100,第1个地址为101,往后累加 若想使用100—150的地址,即首地址为100&#xff…

RHCE9学习指南 第9章 权限管理

9.1 所有者所属组 为了了解所有者和所属组的概念,我们先看图9-1。 图9-1 用房子来帮助理解所有者和所属组 张老板是公司老板,买了一套房作为员工宿舍给A部门的员工居住。张老板是房主,所以他对房子具有很多权限,A部门员工只能具…

小狐狸ChatGPT系统 H5前端底部菜单导航文字修改方法

小狐狸ChatGPT系统后端都前端都是编译过的,需要改动点什么非常难处理,开源版修改后也需要编译后才能使用,大部分会员也不会使用,像简单的修改下底部菜单文字、图标什么的可以对照处理。这里以小狐狸ChatGPT系统1.9.2版本H5端为例&…

35c3 krautflare

参考这篇文章可以彻底了解本题的漏洞所在 https://xz.aliyun.com/t/6527 由于Math.expm1经过patch以后的返回值不可能是-0,但是patch的地方是在typer优化中,所以实际上如果没有优化的话是可以返回-0的,这就意味着如果我们先不停地Math.expm1…