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

前言

在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.mzph.cn/news/558443.shtml

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

相关文章

关键词热度分析工具_谷歌SEO推广排名的关键要素(一)利用谷歌关键词分析工具分析关键词...

大家好,我是谷歌鸿飞,到今年算起,从业谷歌SEO,已经十一个年头了。服务过的外贸企业也有几百家,接触和操作过外贸产品也有上千种。这么多的企业,这么多的产品,思绪万千,不知如何下笔。…

计算机桌面设置定时,如何设置可以每月自动变化的日历桌面?

设置步骤:1、显示电脑桌面(即把所有窗口都最小化);2、Windows Xp和Windows 2000设置有些不同:(windows vista好像不能设置活动桌面)Windows xp:在电脑桌面点击鼠标右键,出现菜单,选择“属性”,然…

系统辨识理论及应用_控制理论学习书单推荐(值得一读)

经 System control 授权,基于控制理论学习书单整理改编。提起系统与控制领域的学习,经常被谈论到的就是,对于刚接触这个领域的初学者总会在各种控制理论中迷茫,有的甚至直接劝退。面对众多理论,完全无从下手。下面就简…

正则只能小于0负数_2019–2020学年七年级数学期末考试考点之正数与负数考点详解...

七年级数学期末考试第一讲之正数与负数考点详解嗨,大家好,这里是摆渡学涯。马上我们就要迎来期末考试了,你们有没有开始复习呢?这次课程咱们来为大家讲一下数的考点,教你轻松学数学。数的概念数从是否为正负数的角度来…

controller接收json数据_SpringMVC实现多种数据类型绑定

点击上方“放学等我”,选择“置顶公众号”精品文章,第一时间送达绑定基本数据类型Java基本数据类型int的默认值是0,在使用int进行url传递参数时,参数key是必须写的,其值也只能是int类型的,否则将会报错。 比…

宝塔设置thinkphp的伪静态_宝塔面板与WDCP狭路相逢,谁才是国产之光?

我本来想给大家写一篇工具类的杂谈,思来想去又想到了可视化面板,就目前国产面板而言,WDCP、宝塔面板、AMH等,说是群雄逐鹿一点都不为过,AMH4.2之后,可以说是走了相当一部分人,暗示收费版本&…

计算机桌面打标签,在电脑桌面上添加便签的方法步骤详解(2)

电脑的桌面便签软件推荐1、CintaNotes电脑的桌面便签软件推荐图1CintaNotes是一款非常轻巧实用的笔记软件,可看作EverNote轻量级替代品。CintaNotes只需1个exe,体积仅1MB,却拥有EverNote易于收集、实时搜索、条状排列、tag分类的优点,更有EverNote 所不具备的中文搜索、纯文本更…

windows。forms.timer设置第一次不等待_适用于初学者的中线交易策略——金叉的三种设置条件...

本文将介绍了使用移动平均线最重要的方法之一——金叉。我们将描述该信号的产生条件,然后深入探讨一下三个交易案例。什么是金叉?当短期移动平均线与长期移动平均线相交时,黄叉就会产生。听起来确实很简单。然而,关键是构成交叉的移动平均线…

python多线程写同一个文件_Python多线程快速写入文件,python,飞速

Python多线程快速写入文件,python,飞速 发表时间:2020-07-10 乱序多线程写入 举个最简单的例子,只要求快速写入即可,对顺序无要求时: import threading def write_string(string, path"test.csv"): with open(path, a) …

2021山东科技大学计算机学院,2021年3月山东科技大学计算机等级考试报名工作通知...

【导语】2021年3月山东科技大学计算机等级考试报名工作通知已公布,为了方便广大考生的查阅,下面无忧考网为您详细介绍一下本次计算机等级考试报名的具体事宜,希望广大考生及时关注,如有相关疑问,敬请关注无忧考网为您实…

html表头的标签,HTML 表头单元格标签

HTML 标签标签定义及使用说明 标签定义 HTML 表格中的表头单元格。HTML 表格有两种单元格类型:表头单元格 - 包含头部信息(由 元素创建)标准单元格 - 包含数据(由 元素创建) 元素中的文本通常呈现为粗体并且居中。 元素中的文本通常是普通的左对齐文本。浏览器支持…

python中计算如何实现_基于python如何实现计算两组数据P值

我们在做A/B试验评估的时候需要借助p_value,这篇文章记录如何利用python计算两组数据的显著性。 一、代码# TTest.py # -*- coding: utf-8 -*-# Created on 2020-05-20 20:36 # TTest.py # author: huiwenhua## Import the packages import numpy as np from scipy import stat…

python自定义函数画图_python matplotlib自定义colorbar颜色条-以及matplotlib中的内置色条...

自定义colorbar(draw colorbar without any mapple/plot) 参考:Customized Colorbars Tutorial api example code: colorbar_only.py 自定义colorbar可以画出任何自己想要的colorbar,自由自在、不受约束,不依赖于任何已…

python绘制饼图程序_python使用Matplotlib绘制饼图

一、函数原型 plt.pie(x, explodeNone, labelsNone, colorsNone, autopctNone, pctdistance0.6, shadowFalse, labeldistance1.1, startangleNone, radiusNone, counterclockTrue, wedgepropsNone, textpropsNone, center(0, 0), frameFalse) 参数: x:绘…

centos选择什么版本_有几千个 Dubbo 实例的瓜子二手车,为什么要选择2.7.3版本?...

随着瓜子业务的不断发展,系统规模在逐渐扩大,目前在瓜子的私有云上已经运行着数百个 Apache Dubbo ( 下文简称 Dubbo )应用,上千个 Dubbo 实例。瓜子各部门业务迅速发展,版本没有来得及统一,各个部门都有自己的用法。随…

w7系统计算机里没有摄像头,win7系统没有摄像头不能视频的几种原因和解决方法...

电脑升级到win7旗舰版系统后,发现摄像头没有了,之前xp系统在硬盘符中就可以打开摄像头的,可是win7系统没有摄像头怎么办呢?这样就没办法视频了,针对此问题,小编研究出原来要从程序里面调出摄像头功能&#…

新计算机 安装win2000,图文教程!Windows 2000安装过程全接触

13、填写计算机名:安装程序提供了文字输入确定用户的计算机名和其它的设置。   在此,需要声明的是:安装程序会创建一个称为Administrator(系统管理员)的用户帐户,它拥有完全控制计算机的权限。确定这个帐户时,安装程序要求用户输入“系统管…

python创建多线程_初学者看过来:Python中多线程和多处理的指南

使用Python分析数据,如果使用了正确的数据结构和算法,有时可以大量提高程序的速度。实现此目的的一种方法是使用Muiltithreading(多线程)或Multiprocessing(多重处理)。 使用Python分析数据,如果使用了正确的数据结构和算法,有时可…

python求50的阶乘_python中求阶乘

广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 我如何去计算python中的一个整数的阶乘?...写一个猜数字的游戏,预先设定一个数字&am…

项目部署服务器 jstl,Springboot集成jsp及部署服务器实现原理

1.在application配置文件里面加入配置:spring:mvc:view:prefix: /jsp/suffix: .jsp2.手动在src->main->下面创建webapp文件夹3.在Springboot 启动类加入如下代码:Beanpublic InternalResourceViewResolver setupViewResolver() {InternalResourceV…