浅拷贝和深拷贝

1、两者区别:

        首先对于一个对象中的基本数据类型,来做浅拷贝和深拷贝其实没有什么区别,都是将原始值复制一份给新的对象,但是对于对象中的引用数据类型来说,浅拷贝只是将引用数据类型的地址值复制一份给新的对象,这样就会导致新对象和旧的对象之间共用一个引用数据,但是深拷贝是直接开辟一个新的内存地址,这样深拷贝的数据和原来的数据是八竿子打不着的!

 2、浅拷贝方式

        在Java中实现浅拷贝通常有几种方法,其中最常见的是使用clone()方法和拷贝构造函数。下面是使用这两种方法来实现浅拷贝的示例:

  • 使用clone()方法:
class MyClass implements Cloneable {private int number;private String text;public MyClass(int number, String text) {this.number = number;this.text = text;}// 实现浅拷贝@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}
}public class Main {public static void main(String[] args) {MyClass original = new MyClass(10, "Hello");try {MyClass copy = (MyClass) original.clone();System.out.println("Original: " + original.getNumber() + ", " + original.getText());System.out.println("Copy: " + copy.getNumber() + ", " + copy.getText());} catch (CloneNotSupportedException e) {e.printStackTrace();}}
}
  • 使用拷贝构造函数:
class MyClass {private int number;private String text;public MyClass(int number, String text) {this.number = number;this.text = text;}// 拷贝构造函数public MyClass(MyClass other) {this.number = other.number;this.text = other.text;}public int getNumber() {return number;}public String getText() {return text;}
}public class Main {public static void main(String[] args) {MyClass original = new MyClass(10, "Hello");MyClass copy = new MyClass(original);System.out.println("Original: " + original.getNumber() + ", " + original.getText());System.out.println("Copy: " + copy.getNumber() + ", " + copy.getText());}
}

        这两种方法都可以实现浅拷贝,但要注意的是,浅拷贝只会复制对象本身及其所有字段的值,如果对象包含引用类型的字段,则复制的是引用,而不是引用指向的对象。

3、深拷贝方式

        深拷贝的实现方式有多种,具体选择哪种方式取决于对象的结构和复杂度。以下是几种常见的实现方式:

  1. 递归复制

    • 对于对象的每一层级,递归地复制其所有字段,包括引用类型字段指向的对象。
    • 这需要确保所有被复制的对象都能被正确地复制,避免循环引用等问题。
  2. 序列化与反序列化

    • 将对象序列化成字节流,然后再反序列化为一个新的对象,这个过程中会创建一个新的对象图,其中的每个对象都是独立的。
    • 这种方式需要确保对象及其所有引用类型字段都是可序列化的。
  3. 手动实现复制构造函数或复制方法

    • 在对象的类中手动实现一个复制构造函数或者复制方法,用于创建一个新的对象并复制所有字段。
    • 这需要确保所有字段都能正确地复制,并且需要考虑到对象图的复杂性。
  4. 使用第三方库

    • 有一些第三方库提供了深拷贝的功能,例如Apache Commons Lang库中的SerializationUtils.clone()方法或者Google Gson库等。

        这些方法各有优缺点,选择合适的实现方式取决于具体的情况和需求。例如,如果对象结构相对简单并且没有循环引用,递归复制可能是一种简单有效的方式。如果对象结构复杂或者存在循环引用,可能需要使用序列化与反序列化或者手动实现复制方法来确保深拷贝的正确性。

递归复用:

import java.util.ArrayList;
import java.util.List;class Person {private String name; // 人员姓名private int age; // 人员年龄private List<String> hobbies; // 人员爱好列表// 构造函数,初始化姓名、年龄和爱好列表public Person(String name, int age, List<String> hobbies) {this.name = name;this.age = age;this.hobbies = hobbies;}// 深拷贝的拷贝构造函数public Person(Person other) {this.name = other.name;this.age = other.age;// 创建一个新的ArrayList并复制所有元素this.hobbies = new ArrayList<>(other.hobbies);}// Getter和Setter方法...
}public class DeepCopyExample {public static void main(String[] args) {List<String> hobbies = new ArrayList<>(); // 创建一个爱好列表hobbies.add("阅读"); // 添加爱好hobbies.add("园艺");Person originalPerson = new Person("Alice", 30, hobbies); // 创建原始的Person对象// 使用拷贝构造函数创建深拷贝Person copiedPerson = new Person(originalPerson);// 修改拷贝的Person对象中的爱好列表copiedPerson.getHobbies().add("烹饪");System.out.println("原始Person对象: " + originalPerson);System.out.println("拷贝的Person对象: " + copiedPerson);}
}

 序列化和反序列化:

import java.io.*;// 定义一个可序列化的类
class Person implements Serializable {private String name; // 姓名private int age; // 年龄private List<String> hobbies; // 爱好列表// 构造函数,初始化姓名、年龄和爱好列表public Person(String name, int age, List<String> hobbies) {this.name = name;this.age = age;this.hobbies = hobbies;}// 序列化方法public byte[] serialize() throws IOException {ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream out = new ObjectOutputStream(bos);out.writeObject(this);out.close();return bos.toByteArray();}// 反序列化方法public static Person deserialize(byte[] data) throws IOException, ClassNotFoundException {ByteArrayInputStream bis = new ByteArrayInputStream(data);ObjectInputStream in = new ObjectInputStream(bis);Person person = (Person) in.readObject();in.close();return person;}// Getter和Setter方法...// toString方法...
}public class DeepCopySerializationExample {public static void main(String[] args) throws IOException, ClassNotFoundException {List<String> hobbies = new ArrayList<>(); // 创建一个爱好列表hobbies.add("阅读"); // 添加爱好hobbies.add("园艺");Person originalPerson = new Person("Alice", 30, hobbies); // 创建原始的Person对象// 使用序列化和反序列化进行深拷贝byte[] serializedData = originalPerson.serialize();Person copiedPerson = Person.deserialize(serializedData);// 修改拷贝的Person对象中的爱好列表copiedPerson.getHobbies().add("烹饪");// 打印原始Person对象和拷贝的Person对象System.out.println("原始Person对象: " + originalPerson);System.out.println("拷贝的Person对象: " + copiedPerson);}
}

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

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

相关文章

python开发poc,fofa爬虫批量化扫洞

学习使用python做到批量化的漏洞脚本 1.通过fofa搜索结果来采集脚本 2.批量化扫描漏洞 ---glassfish存在任意文件读取在默认48484端口&#xff0c;漏洞验证的poc为: "glassfish" && port"4848" && country"CN" http://loca…

Sybase ASE中的char(N)的坑以及与PostgreSQL的对比

1背景 昨天,一朋友向我咨询Sybase ASE中定长字符串类型的行为,说他们的客户反映,同样的char类型的数据,通过jdbc来查,Sybase库不会带空格,而PostgreSQL会带。是不是这样的?他是PostgreSQL的专业大拿,但因为他手头没有现成的Sybase ASE环境,刚好我手上有,便于一试。 …

flutter 安卓打包自定义名字

打包的名字如 app.1.0.1_relase_201283893.apk 实现 配置安卓项目的中的build.gradle &#xff08;android/app/build.gradle &#xff09; 新增 android { 内 applicationVariants.all { variant ->variant.outputs.all {def appName "拓车服管家" // 文件名…

Python实现读取dxf文件的所有字符

Python实现读取dxf文件的所有字符 import ezdxfdef read_dxf_and_print_text(filename):# 加载DXF文件doc ezdxf.readfile(filename)# 遍历所有的实体for entity in doc.entities:# 检查实体是否是TEXT、MTEXT或DIMENSIONif isinstance(entity, ezdxf.entities.Text):print(f…

SparkBug解决:Type mismatch; found : org.apache.spark.sql.Column required: Double

def assginFlag(aizmuth:Double):Option[Int] {val interval 0.5val index (aizmuth / interval ).toIntif (index > 0 && index < 720 ) Some(index 1) else None} assginFlag方法中的条件判断条件 (index > 0 && index < 720) 返回的是一个布…

计算机视觉——图像特征提取D2D先描述后检测特征提取算法原理

概述 局部特征提取是计算机视觉中的一个重要任务&#xff0c;它旨在从图像中提取出能够代表图像局部结构和外观信息的特征。这些特征通常用于图像匹配、物体识别、三维重建、跟踪和许多其他应用。传统方法&#xff0c;如尺度不变特征变换&#xff08;SIFT&#xff09;&#xf…

每天学习一个Linux命令之hostnamectl

每天学习一个Linux命令之hostnamectl 介绍 在Linux系统中&#xff0c;有许多命令都可以用来管理系统的各种配置&#xff0c;其中之一就是hostnamectl命令。hostnamectl命令可以用于查看和更改系统的主机名及相关设置。本篇博客将为您详细介绍hostnamectl命令&#xff0c;并列…

使用R语言计算矩形分布(均匀分布)并绘制图形

理论部分 矩形分布&#xff08;均匀分布&#xff09;&#xff0c;是指在某一区间内&#xff0c;随机变量取任何值的概率都是相同的。这种分布的概率密度函数在一个特定的区间内是一个常数&#xff0c;因此其图形呈现出一个矩形的形状&#xff0c;故得名为“矩形分布”。在概率…

【Spring进阶系列丨第八篇】Spring整合junit 面向切面编程(AOP)详解

文章目录 一、Spring整合junit1.1、导入spring整合junit的jar1.2、在测试类上添加注解1.3、说明 二、面向切面编程(AOP)2.1、问题引出2.2、AOP2.2.1、概念2.2.2、作用2.2.3、优势2.2.4、实现方式2.2.5、专业术语2.2.5.1、连接点2.2.5.2、切入点2.2.5.3、通知/增强2.2.5.4、织入…

5款最值得推荐的电脑监控软件丨高人气甄选

在企业和学校等场所&#xff0c;电脑监控软件被广泛应用于员工或学生的行为管理。 通过监控软件&#xff0c;管理者可以了解员工或学生的学习和工作情况&#xff0c;及时发现并纠正不当行为&#xff0c;提高工作效率和学习效果。同时&#xff0c;这类软件还可以用于保护企业机…

世链空投|zkLink空投代撸有哪些好处?zkLink空投代撸需要啥条件

世链空投(shilian.com)报道&#xff0c;随着2024年zkLink空投越来越火&#xff0c;zkLink空投代撸已经成为普通人一种常见的参与方式&#xff0c;并且越来越受到大众的欢迎。但是&#xff0c;普通人想要参与zkLink空投代撸&#xff0c;仍然需要了解什么是zkLink空投代撸&#x…

CMD 操作

修复磁盘 打开命令提示符&#xff0c;输入“chkdsk G: /f”&#xff08;G:代表你需要修复的硬盘驱动器&#xff0c;/f代表修复错误&#xff09; 安装软件 python安装包&#xff0c;打开CMD, pip install 〔*包〕

AI概念普及-LangChain

文章目录 概念产品架构核心特性核心组件使用场景其他资源开发支持结论Langchain详细介绍LangChain的具体实现原理LangChain如何与其他大型语言模型&#xff08;LLM&#xff09;集成&#xff0c;有哪些具体的接口或协议&#xff1f;LangChain的性能表现和优化策略有哪些&#xf…

【多线程】线程(线程的概念+线程的创建)

文章目录 线程一、线程的概念1.引入线程的目的2.什么叫线程&#xff08;Thread&#xff09;1.线程的特点&#xff1a;2.进程和线程的区别&#xff08;面试题&#xff09;&#xff1a;3.Java的多线程编程 二、创建线程1.继承Thread重写run入口方法&#xff1a;使用jconsolesleep…

Games101-光线追踪(加速结构)

Bounding Volumes 包围盒&#xff1a;用一个简单形状把物体包围起来&#xff0c;如果物体连包围盒都无法碰撞&#xff0c;一定无法碰撞包围盒内的物体 将长方体理解成三个不同对面形成的交集&#xff0c;一定是在x&#xff0c;y&#xff0c;z轴上的范围。没有旋转 Ray Inters…

适用于 Windows 10 的 10 大免费数据恢复软件

数据丢失可能是一场噩梦&#xff0c;尤其是在涉及重要文件和文档时。无论是由于意外删除、系统崩溃还是病毒攻击&#xff0c;找到适合 Windows 10 的文件夹恢复软件都可以在恢复丢失的数据方面发挥重要作用。在本指南中&#xff0c;我们将探索适用于 Windows 10 用户的 10 大免…

加密方法字段uuid标识

58b16292-260b-60bd-44a7-796e3ed4f20e 是uuid python实现 import uuidprint(uuid.uuid4())是的&#xff0c;7bff3132-952a-4338-9df4-544383e81a2a 是一个典型的UUID&#xff08;Universally Unique Identifier&#xff0c;通用唯一识别码&#xff09;格式的字符串。UUID是一…

mysql解锁表及查看表是否被锁

1、查进程&#xff0c;查找被锁表的那个进程的ID show processlist; 2、通过查询结果&#xff0c;找到要杀掉的进程&#xff0c;kill掉锁表的进程ID kill id; 3、查询是否锁表 show OPEN TABLES where In_use > 0; 1.delete------ 是逐行删除速度极慢&#xff0c;不适合…

如何使用Python中的logging模块进行日志记录?

如何使用Python中的logging模块进行日志记录&#xff1f; Python中的logging模块是一个强大的工具&#xff0c;用于记录应用程序的运行时信息。它提供了灵活的日志记录系统&#xff0c;允许开发者定义不同级别的日志消息&#xff0c;并可以选择将这些消息输出到不同的目标&…

【退役之重学Java】pom文件没啥问题但报红

复制过来的pom文件&#xff0c;有几处版本号报红 刚开始以为是版本号的问题&#xff0c;但是按道理从大佬那里复制过来的&#xff0c;应该不会有问题&#xff0c;还是检查了一下&#xff1a; 把项目压缩发给师傅&#xff0c;师傅哪里没报错好吧&#xff0c;我已经猜到了为什么……