深克隆和浅克隆

news2025/1/8 11:47:40

1. 浅克隆 (Shallow Copy)

浅克隆指的是创建一个新的对象,并将原始对象的字段值复制到新对象中。如果字段是基本数据类型(如 intchar 等),则直接复制这些值。如果字段是引用类型(如数组、对象等),则复制的是引用,而不是创建新的对象。因此,浅克隆后的对象和原始对象共享引用类型的字段(例如,引用类型的字段指向相同的内存地址)。

浅克隆的特点:
  • 对于基本数据类型,进行的是值的复制。
  • 对于引用类型,进行的是引用的复制,即原始对象和克隆对象中的引用指向同一个内存位置。

示例:

class Person {
    String name;
    int age;
    int[] scores;

    public Person(String name, int age, int[] scores) {
        this.name = name;
        this.age = age;
        this.scores = scores;
    }

    // 浅克隆
    public Person shallowClone() {
        try {
            return (Person) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

public class ShallowCopyExample {
    public static void main(String[] args) {
        int[] scores = {85, 90, 88};
        Person person1 = new Person("Tom", 20, scores);
        Person person2 = person1.shallowClone();

        // 修改 person2 的 scores 数组
        person2.scores[0] = 100;

        // person1 的 scores 数组也会被修改,因为是引用类型的浅克隆
        System.out.println("person1 scores[0]: " + person1.scores[0]); // 100
        System.out.println("person2 scores[0]: " + person2.scores[0]); // 100
    }
}

输出:

person1 scores[0]: 100
person2 scores[0]: 100

在这个例子中,person1person2 共享相同的 scores 数组,修改其中一个对象的数组会影响到另一个对象。

2. 深克隆 (Deep Copy)

深克隆指的是创建一个新的对象,并递归地复制原始对象中的所有字段。对于基本数据类型,值会被直接复制;对于引用类型,会复制出一份新的对象,这意味着原始对象和克隆对象中的引用类型字段指向的是不同的内存位置。因此,深克隆的对象与原始对象完全独立,即使修改克隆对象的引用类型字段,也不会影响原始对象。

深克隆的特点:
  • 对于基本数据类型,进行的是值的复制。
  • 对于引用类型,进行的是对象的递归复制,创建新的对象,使得原始对象和克隆对象中的引用类型字段指向不同的内存位置。
举个例子:
class Person implements Cloneable {
    String name;
    int age;
    int[] scores;

    public Person(String name, int age, int[] scores) {
        this.name = name;
        this.age = age;
        this.scores = scores;
    }

    // 深克隆
    @Override
    public Person clone() {
        try {
            Person cloned = (Person) super.clone();
            cloned.scores = cloned.scores.clone(); // 对 scores 进行深克隆
            return cloned;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

public class DeepCopyExample {
    public static void main(String[] args) {
        int[] scores = {85, 90, 88};
        Person person1 = new Person("Tom", 20, scores);
        Person person2 = person1.clone();

        // 修改 person2 的 scores 数组
        person2.scores[0] = 100;

        // person1 的 scores 数组不会受到影响
        System.out.println("person1 scores[0]: " + person1.scores[0]); // 85
        System.out.println("person2 scores[0]: " + person2.scores[0]); // 100
    }
}

输出:

person1 scores[0]: 85
person2 scores[0]: 100

在这个例子中,person1person2 拥有不同的 scores 数组。修改其中一个对象的数组不会影响另一个对象。

3. 深克隆与浅克隆的区别总结

特性浅克隆 (Shallow Copy)深克隆 (Deep Copy)
基本数据类型复制基本数据类型的值同样复制基本数据类型的值
引用类型(数组、对象等)复制引用类型的引用,原始对象与克隆对象共享引用类型字段复制引用类型的对象,原始对象与克隆对象的引用类型字段指向不同的内存地址
适用场景对于不包含嵌套对象或引用类型的简单对象,或者希望共享引用对象时当需要确保克隆对象与原对象完全独立,尤其是当对象中包含嵌套引用对象时

4. 深克隆与浅克隆的实现方式

  • 浅克隆可以通过实现 Cloneable 接口并重写 clone() 方法来实现,Java 的 Object 类提供了 clone() 方法,默认实现是浅克隆。

  • 深克隆需要手动处理引用类型的字段,通过调用 clone() 或使用其他方法(如序列化)来复制引用类型的对象。

深克隆的其他实现方式:

选择使用浅克隆还是深克隆,取决于具体的需求,尤其是在对象中是否包含可变的引用类型字段时。

  • 序列化方式:通过将对象序列化后再反序列化来实现深克隆。这样可以自动处理所有字段的复制,包括引用类型字段。

    import java.io.*;
    
    public class DeepCloneUsingSerialization {
        public static <T> T deepClone(T obj) throws IOException, ClassNotFoundException {
            // 写入字节流
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(bos);
            out.writeObject(obj);
            out.flush();
    
            // 读取字节流并返回新对象
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream in = new ObjectInputStream(bis);
            return (T) in.readObject();
        }
    }
    

    总结

  • 浅克隆只复制对象本身,不会递归复制引用类型字段,因此它们会共享引用类型的数据。
  • 深克隆会递归地复制对象中的所有字段,包括引用类型字段,因此它们互不影响,完全独立。

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

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

相关文章

【VScode】设置代理,通过代理连接服务器

文章目录 VScode编辑器设置代理1.图形化界面1.1 进入proxy设置界面1.2 配置代理服务器 2.配置文件&#xff08;推荐&#xff09;2.1 打开setting.json 文件2.2 配置代理 VScode编辑器设置代理 根据情况安装nmap 1.图形化界面 1.1 进入proxy设置界面 或者使用快捷键ctrl , 。…

【HarmonyOS】鸿蒙应用点9图的处理(draw9patch)

【HarmonyOS】鸿蒙应用点9图的处理&#xff08;draw9patch&#xff09; 一、前言&#xff1a; 首先在鸿蒙中是不支持安卓 .9图的图片直接使用。只有类似拉伸的处理方案&#xff0c;鸿蒙提供的Image组件有与点九图相同功能的API设置。 可以通过设置resizable属性来设置Resiza…

光伏仿真与设计系统应用架构深度剖析

在光伏产业蓬勃发展的时代背景下&#xff0c;绿虫光伏仿真与设计系统成为推动其高效发展的核心力量。其应用架构涵盖多个关键步骤&#xff0c;每个环节都紧密相扣&#xff0c;共同构建起精准且高效的设计体系。 气象分析作为开篇之笔&#xff0c;起着基石般的重要作用。系统全…

k8s dashboard离线部署步骤

确定k8s版本&#xff0c;以1.23为例。 部署metrics-server服务&#xff0c;最好用v0.5.2。 用v0.6.0&#xff0c;可能会报以下错误&#xff1a; nodekubemaster:~/Desktop/metric$ kubectl top nodes Error from server (ServiceUnavailable): the server is currently unabl…

05-Linux系统编程之进程(下)

一、子进程资源回收 1.概述 在每个进程退出的时候&#xff0c;内核释放该进程所有的资源&#xff0c;包括一些存储在栈区、全局区的数据、打开的文件、占用的内存等。但是仍有一部分信息没有释放&#xff0c;这些信息主要指进程控制块 PCB 的信息&#xff08;包括进程号、退出…

HDFS异构存储和存储策略

一、HDFS异构存储类型 1.1 冷、热、温、冻数据 通常&#xff0c;公司或者组织总是有相当多的历史数据占用昂贵的存储空间。典型的数据使用模式是新传入的数据被应用程序大量使用&#xff0c;从而该数据被标记为"热"数据。随着时间的推移&#xff0c;存储的数据每周…

【51单片机】02LED流水灯实验

点亮你的LED 一、点亮第一个LED1.GPIO介绍2.P1、P2、P3端口 二、LED实验2.尝试点亮LED3.LED流水灯 一、点亮第一个LED 1.GPIO介绍 这块内容这里可以做简单的了解&#xff0c;与数电知识强相关。后续可以再回过头来学习 GPIO (general purpose input output) 通用输入输出端口…

springboot 集成 etcd

springboot 集成 etcd 往期内容 ETCD 简介docker部署ETCD 前言 好久不见各位小伙伴们&#xff0c;上两期内容中&#xff0c;我们对于分布式kv存储中间件有了简单的认识&#xff0c;完成了docker-compose 部署etcd集群以及可视化工具 etcd Keeper&#xff0c;既然有了认识&a…

云安全相关博客阅读(一)

2024-03-04 Cloudflare announces Firewall for AI 关注问题&#xff1a; 传统的WAF功能能够保护web和api安全&#xff0c;但是随着LLM等AI模型等出现&#xff0c;保护这些AI相关应用等安全是一个新出现的问题虽然AI应用是新的场景&#xff0c;但是以往的攻击方法也能够直接用…

2025年01月07日Github流行趋势

项目名称&#xff1a;khoj 项目地址url&#xff1a;https://github.com/khoj-ai/khoj项目语言&#xff1a;Python历史star数&#xff1a;20105今日star数&#xff1a;363项目维护者&#xff1a;debanjum, sabaimran, MythicalCow, aam-at, shantanuSakpal项目简介&#xff1a;你…

从零手写线性回归模型:PyTorch 实现深度学习入门教程

系列文章目录 01-PyTorch新手必看&#xff1a;张量是什么&#xff1f;5 分钟教你快速创建张量&#xff01; 02-张量运算真简单&#xff01;PyTorch 数值计算操作完全指南 03-Numpy 还是 PyTorch&#xff1f;张量与 Numpy 的神奇转换技巧 04-揭秘数据处理神器&#xff1a;PyTor…

【python】matplotlib(radar chart)

文章目录 1、功能描述和原理介绍2、代码实现3、效果展示4、完整代码5、多个雷达图绘制在一张图上6、参考 1、功能描述和原理介绍 基于 matplotlib 实现雷达图的绘制 一、雷达图的基本概念 雷达图&#xff08;Radar Chart&#xff09;&#xff0c;也被称为蛛网图或星型图&…

数据库环境安装(day1)

网址&#xff1a;MySQL 下载&#xff08;环境准备&#xff09;&#xff1a; &#xff08;2-5点击此处&#xff0c;然后选择合适的版本&#xff09; 1.linux在线YUM仓库 下载/安装: wget https://repo.mysql.com//mysql84-community-release-el9-1.noarch.rpm rpm -i https://r…

Fabric链码部署测试

参考链接&#xff1a;运行 Fabric 应用程序 — Hyperledger Fabric Docs 主文档 (hyperledger-fabric.readthedocs.io) &#xff08;2&#xff09;fabric2.4.3部署运行自己的链码 - 知乎 (zhihu.com) Fabric2.0测试网络部署链码 - 辉哥哥~ - 博客园 (cnblogs.com) 1.启动测试…

数据结构与算法之二叉树: LeetCode 107. 二叉树的层序遍历 II (Ts版)

二叉树的层序遍历 II https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/description/ 描述 给你二叉树的根节点 root &#xff0c;返回其节点值 自底向上的层序遍历 。 &#xff08;即按从叶子节点所在层到根节点所在的层&#xff0c;逐层从左向右遍历&a…

Python插件化开发实战:开发个图片浏览器

在本篇教程中&#xff0c;我将详细介绍如何使用Python开发一个基于插件架构的图片浏览器。这个项目将展示如何实现插件系统、如何处理图片显示,以及如何使用wxPython构建GUI界面。 “C:\pythoncode\pythonplugin\your_project\main_app.py” 项目概述 我们将开发一个具有以下…

根据python代码自动生成类图的实现方法[附带python源码]

概述 利用python库抽象语法树(AST)和类图描述语言(PlantUML),实现自动将python代码生成类图的目的。 环境 windowsvscodepythonplantuml ✒️网上好像大部分都是用Pyreverse库来实现的&#xff0c;但是我实际测试发现只能在一个文件中才能行&#xff0c;当然应该有解决方法…

下载b站高清视频

需要使用的edge上的一个扩展插件&#xff0c;所以选择使用edge浏览器。 1、在edge浏览器上下载 强力视频下载合并 扩展插件 2、在edge上打开b站&#xff0c;登录自己账号&#xff08;登录后才能下载到高清&#xff01;&#xff01;&#xff09;。打开一个视频&#xff0c;选择自…

flutter 专题二十四 Flutter性能优化在携程酒店的实践

Flutter性能优化在携程酒店的实践 一 、前言 携程酒店业务使用Flutter技术开发的时间快接近两年&#xff0c;这期间有列表页、详情页、相册页等页面使用了Flutter技术栈进行了跨平台整合&#xff0c;大大提高了研发效率。在开发过程中&#xff0c;也遇到了一些性能相关问题和…

UE5 打包要点

------------------------- 1、需要环境 win sdk &#xff0c;大约3G VS&#xff0c;大约10G 不安装就无法打包&#xff0c;就是这么简单。 ----------------------- 2、打包设置 编译类型&#xff0c;开发、调试、发行 项目设置-地图和模式&#xff0c;默认地图 项目…