【java深拷贝和浅拷贝区别是什么?】

文章目录

    • Java深拷贝和浅拷贝的区别
      • (1)浅拷贝(Shallow Copy)
      • (2)深拷贝(Deep Copy)
    • 总结

Java深拷贝和浅拷贝的区别

在Java中,深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是对象复制时的两种策略,它们的主要区别在于复制的深度和对象的引用关系处理上。

(1)浅拷贝(Shallow Copy)

浅拷贝只复制对象的基本数据类型字段值和引用类型字段的内存地址(即引用),而不复制引用类型字段所指向的对象本身。因此,原对象和拷贝对象共享对同一个引用类型对象的引用。对拷贝对象修改非基本数据类型字段会影响到原对象,因为它们引用的是同一个对象。

在Java中,使用赋值运算符=、拷贝构造函数或实现了Cloneable接口并使用Object.clone()方法进行的拷贝通常是浅拷贝。

  • 示例
    假设我们有一个简单的Person类,它包含一个基本数据类型字段和一个引用类型字段(例如Address):
import java.util.Objects;  class Address {  String street;  String city;  // 构造器、getter和setter省略  @Override  public boolean equals(Object o) {  if (this == o) return true;  if (o == null || getClass() != o.getClass()) return false;  Address address = (Address) o;  return Objects.equals(street, address.street) &&  Objects.equals(city, address.city);  }  @Override  public int hashCode() {  return Objects.hash(street, city);  }  
}  class Person implements Cloneable {  String name;  Address address;  // 构造器、getter和setter省略  @Override  protected Person clone() throws CloneNotSupportedException {  return (Person) super.clone(); // 浅拷贝  }  // 为了演示,重写toString方法  @Override  public String toString() {  return "Person{" +  "name='" + name + '\'' +  ", address=" + address +  '}';  }  
}  public class ShallowCopyExample {  public static void main(String[] args) throws CloneNotSupportedException {  Address address = new Address();  address.street = "123 Main St";  address.city = "Anytown";  Person originalPerson = new Person();  originalPerson.name = "John Doe";  originalPerson.address = address;  Person clonedPerson = originalPerson.clone();  clonedPerson.address.city = "New City"; // 修改拷贝对象的地址  System.out.println(originalPerson); // 输出将显示地址已被修改  System.out.println(clonedPerson);  }  
}

在这个例子中,当我们修改clonedPerson的地址时,originalPerson的地址也会被修改,因为它们引用的是同一个Address对象。

(2)深拷贝(Deep Copy)

深拷贝会复制对象的所有字段值,包括基本数据类型和引用类型字段。对于引用类型字段,深拷贝会创建一个新的对象,并复制原对象中的引用类型字段所指向的对象到新对象中。因此,原对象和拷贝对象是完全独立的,对拷贝对象的修改不会影响到原对象。

在Java中,实现深拷贝通常需要手动编写代码或使用序列化(Serialization)和反序列化(Deserialization)的方式来实现。通过序列化将对象转换为字节序列,然后反序列化这些字节序列来创建一个新的对象,从而实现深拷贝。

  • 示例
    为了进行深拷贝,我们需要确保所有引用类型字段都被复制,并创建新的对象实例:
class Person implements Cloneable {  String name;  Address address;  // 构造器、getter和setter省略  @Override  protected Object clone() throws CloneNotSupportedException {  Person cloned = (Person) super.clone(); // 浅拷贝Person对象  cloned.address = (Address) address.clone(); // 假设Address也实现了Cloneable并覆盖了clone方法  return cloned;  }  // 为了演示,假设Address类也实现了Cloneable并覆盖了clone方法  // ...  // toString方法省略  
}  // Address类也需要实现Cloneable并覆盖clone方法  
class Address implements Cloneable {  String street;  String city;  // 构造器、getter、setter和clone方法省略  // toString方法省略  
}  public class DeepCopyExample {  public static void main(String[] args) throws CloneNotSupportedException {  // ... 初始化originalPerson的代码与ShallowCopyExample相同 ...  Person deepClonedPerson = (Person) originalPerson.clone(); // 进行深拷贝  deepClonedPerson.address.city = "New City"; // 修改拷贝对象的地址  System.out.println(originalPerson); // 输出将不会显示地址已被修改  System.out.println(deepClonedPerson);  }  
}

在这个深拷贝的例子中,即使我们修改了deepClonedPerson的地址,originalPerson的地址也不会被修改,因为它们引用的是不同的Address对象实例。注意,在实际应用中,如果对象图很复杂,可能需要使用更复杂的深拷贝策略,如序列化/反序列化或使用专门的库(如Apache Commons Lang的SerializationUtils)来实现深拷贝。

总结

在面试中,可以这样总结深拷贝和浅拷贝的区别:

深拷贝和浅拷贝的主要区别在于对引用类型字段的处理上。浅拷贝只复制引用类型字段的内存地址,而深拷贝会创建一个新的对象并复制原对象中的引用类型字段所指向的对象到新对象中。因此,浅拷贝的拷贝对象和原对象共享对同一个引用类型对象的引用,而深拷贝的拷贝对象和原对象是完全独立的。

在实现深拷贝时,需要注意递归地复制对象的所有字段,包括嵌套的对象和集合等。如果对象的字段中包含循环引用,则需要特别处理以避免无限递归。此外,深拷贝通常比浅拷贝更消耗资源,因为它需要创建新的对象并复制对象的所有字段值。

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

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

相关文章

【面试干货】SQL中count(*)、count(1)和count(column)的区别与用法

【面试干货】SQL中count(*)、count(1)和count(column)的区别与用法 1、count(*)2、count(1)3、count(column) 💖The Begin💖点点关注,收藏不迷路💖 在SQL中&a…

Oracle作业调度器Job Scheduler

Oracle数据库调度器 (Oracle Database Scheduler) 在数据库管理系统中,数据库调度器负责调度和执行数据库中的存储过程、触发器、事件等。它可以确保这些操作在正确的时间和条件下得到执行,以满足业务需求。 1、授权用户权限 -- 创建目录对象 tmp_dir…

5.4.18 加载某三方模块使用内核 panic 问题分析

环境信息 内核版本:5.4.18 cpu 架构:arm64 问题描述 加载了产品的某三方 ko 文件使用过程中,会触发如下 panic 信息: [ 218.133479][ 0] Unable to handle kernel NULL pointer dereference at virtual address 0000000000…

CSS函数:fit-content与matrix的使用

网格函数 fit-content()属于网格函数,除此之外的网格函数还有:CSS函数: 实现数据限阈的数字函数。顾名思义,这三个函数只能在网格布局中使用。fit-content()函数主要是用于给定布局可用大小,适应内容,其功…

MySQL事务与MVCC

文章目录 事务和事务的隔离级别1.为什么需要事务2.事务特性1_原子性(atomicity)2_一致性(consistency)3_持久性(durability)4_隔离性(isolation) 3.事务并发引发的问题1_脏读2_不可重…

基于小波域优化Savitzky–Golay滤波器的脑电图信号的运动伪影去除方法(MATLAB R2018A)

在获取或采集数据的过程中,不可避免地将噪声引入到数据中,噪声的存在使得原始数据发生变异,对数据的处理及分析产生严重地影响。常用的去噪模型有平滑去噪、均值去噪。其中,平滑去噪又包括移动平均平滑法和Savitzky-Golay卷积平滑…

一周学会Django5 Python Web开发 - Django5内置Auth认证系统-用户注册实现

锋哥原创的Python Web开发 Django5视频教程: 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计57条视频,包括:2024版 Django5 Python we…

keil下载及安装(社区版本)

知不足而奋进 望远山而前行 目录 文章目录 前言 Keil有官方版本和社区版本,此文章为社区版本安装,仅供参考。 1.keil MDK 2.keil社区版介绍 3.keil下载 (1)打开进入登录界面 (2)点击下载,跳转到信息页面 (3)填写个人信息,点击提交 (4)点击下载…

韩国Neowine推出第三代强加密芯片ALPU-CV

推出第三代加密芯片;是ALPU系列中的高端IC;是一款高性能车规级加密芯片;其加密性更强、低耗电、体积小;使得防复制、防抄袭板子的加密性能大大提升,该芯片通过《AEC-Q100》认证,目前已经在国产前装车辆配件…

VMware Workstation虚拟机安装 CentOS 7.9 后ping ip地址出现错误:Network is unreachable

VMware Workstation虚拟机安装 CentOS 7.9 后ping ip地址出现错误:Network is unreachable 解决步骤: 进入目录 进入/etc/sysconfig/network-scripts/, cd /etc/sysconfig/network-scripts/修改文件 vi ifcfg-ens33变更项 ONBOOTyes保存…

算法学习笔记(7.6)-贪心算法(霍夫曼编码)

目录 1.什么是霍夫曼树 2.霍夫曼树的构造过程 3.霍夫曼编码 3.1具体的作用-频率统计 ##实战题目 1.什么是霍夫曼树 给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也…

ast.js是什么?

在devtools分析网站时,出现了ast.js的页面。那么,什么是ast.js?它有什么用? 经查询,AST是抽象语法树(Abstract Syntax Tree)也称为AST语法树,指的是源代码语法所对应的树状结构。也就是说&…

vue3+uniapp

1.页面滚动 2.图片懒加载 3.安全区域 4.返回顶部,刷新页面 5.grid布局 place-self: center; 6.模糊效果 7.缩放 8.微信小程序联系客服 9.拨打电话 10.穿透 11.盒子宽度 12.一般文字以及盒子阴影 13.选中文字 14.顶部安全距离 15.onLoad周期函数在setup语法糖执行后…

论文阅读:Neural Scene Flow Prior

目录 概要 Motivation 整体架构流程 技术细节 小结 论文地址:

基于GTX 8B10B编码的自定义PHY上板测试(高速收发器十四)

前文整理了GTX IP,完成了自定义PHY协议的收发模块设计,本文将通过光纤回环,对这些模块上板测试,首先需要编写一个用于生成测试数据的用户模块。 1、测试数据生成模块 本模块用于生成自定义PHY协议的测试数据,通过axi_…

期望18K,4年前端Cvte 视源股份一面挂

一面 1、自我介绍?毕业的时候一直在 xx 公司,你基本都在做什么项目? 2、你讲一下你主要负责哪一块的?balabala 3、你们的 json 是怎么定义组件间的联动的? 4、怎么确定区分两个 input? 5、你们是怎么触…

软件三班20240605

文章目录 1.创建工程和模块2.添加 web支持3.创建前端代码4.添加servlet 依赖5. 代码6.案例2 1.创建工程和模块 2.添加 web支持 方法1 方法2 3.创建前端代码 4.添加servlet 依赖 5. 代码 <!DOCTYPE html> <html lang"en"> <head><meta c…

Spring Boot中的JDK 线程池以及Tomcat线程池使用与配置

Spring Boot中的线程池使用与配置 一、引言 在Java开发中&#xff0c;特别是在高并发场景下&#xff0c;线程池是一个非常重要的概念。合理地使用线程池可以优化系统性能&#xff0c;避免线程频繁创建和销毁带来的性能开销。Spring Boot作为当前最流行的Java框架之一&#xf…

VBA模拟题库生成器

VBA模拟题库生成器 Option ExplicitDim intXZ As Integer 选择题数 Dim intPD As Integer 判断题数 Dim intTK As Integer 填空题数 Dim intWD As Integer 问答题数 Dim intNon As Integer 未知题数 Dim intCount As Integer 题库行数 Dim intCol As Integer …