java面试基础 -- 深克隆 浅克隆

news2024/9/20 14:30:16

引例

        说到java的克隆你还记得多少? 一说到克隆你可能就会想起来那个接口, 没错, 他就是Cloneable

        Cloneable是java里面内置的很常用的接口, 我们说 Object类中也有一个clone方法:

         但是要想合法调用 clone 方法, 必须要先实现 Clonable 接口, 否则就会抛出 CloneNotSupportedException 异常.

         于是, 我们创建一个类为Dog类, 如下:

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        Dog dog1 = new Dog();
        Dog dog2 = (Dog) dog1.clone();
        System.out.println(dog1 == dog2);
    }
}

class Dog implements Cloneable {
    public String dogName;

    public int dogAge;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Dog newDog = null;
        newDog = (Dog) super.clone();
        return newDog;
    }
}

输出结果:




深克隆 vs 浅克隆

        浅克隆只复制对象本身和对象的本数据类型字段,而不复制引用类型字段所指向的对象.
这里的引用类型, 可以是类的引用, 也可以是字符串等.

        我们说实现了Cloneable接口的类拷贝出来的对象是浅拷贝还是深拷贝??? 

案例:

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        Animal animal1 = new Animal();
        Animal animal2 = (Animal) animal1.clone();
        animal2.classIn = 2;
        animal2.dog.name = "小白";
        System.out.println(animal1.toString());
        System.out.println(animal2.toString());
    }
}

class Dog {
    String name = "小黑";
}
class Animal implements Cloneable {
    public Dog dog = new Dog();

    public int classIn = 1;

    @Override
    public String toString() {
        return "Animal{" +
                "dogName=" + dog.name +
                ", classIn=" + classIn +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

输出结果:

        可以看出来, 他们里面的类的实例却是共享的, 里面的类的引用不同, 但是引用的是同一个类对象. 这就是浅拷贝. 




如何深克隆

深克隆:基本数据类型变量和引用类型变量指向的对象都会被复制,即针对引用类型的成员变量真正的复制一份,重新开辟空间保存,这样两个引用类型属性互不影响。

        那么如何进行深拷贝呢??

         很容易想到的一点就是, 在重写object中的clone方法, 然后对被克隆的类里面的类引用继续克隆. 也就是嵌套克隆

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        Animal animal1 = new Animal();
        Animal animal2 = (Animal) animal1.clone();
        animal2.classIn = 2;
        animal2.dog.name = "小白";
        System.out.println(animal1.toString());
        System.out.println(animal2.toString());
    }
}

class Dog implements Cloneable{
    String name = "小黑";

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Animal implements Cloneable {
    public Dog dog = new Dog();

    public int classIn = 1;

    @Override
    public String toString() {
        return "Animal{" +
                "dogName=" + dog.name +
                ", classIn=" + classIn +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Animal newAnimal = (Animal) super.clone();
        newAnimal.dog = (Dog) dog.clone();
        return  newAnimal;
    }
}

输出结果:




总结

  • 在Java中,克隆操作可以分为浅克隆和深克隆两种方式。浅克隆只复制对象本身和对象的本数据类型字段,而不复制引用类型字段所指向的对象。深克隆则会复制对象本身以及对象的引用类型字段所指向的对象,即完全复制了整个对象的所有内容。
  • 浅克隆是通过调用对象的clone()方法来实现的,它会创建一个新的对象,并将原对象的字段值复制到新对象中。但是,新对象和原对象共享同一个引用类型字段对象,所以改变其中一个对象的引用类型字段会影响到另一个对象。
  • 深克隆需要在克隆方法中对引用类型字段进行递归复制。具体实现方法是,在克隆方法中调用引用类型字段的clone()方法来复制该字段所指向的对象。这样就可以创建一个新的对象,并将原对象的所有字段值和引用类型字段所指向的对象的字段值都复制到新对象中,实现了完全独立的克隆。
  • 总结来说,浅克隆只复制对象本身和基本数据类型字段,而深克隆会复制整个对象的所有内容,包括引用类型字段所指向的对象。

引用: :java中的克隆有浅克隆和深克隆之分,造成这种区别是因为java中对于基本数据类型和引用类型类型的存储是不一样的,基本数据类型存储在栈中,而引用数据类型存储在堆中,因此造成了在克隆时的不同操作。 :针对上面的例子只需要在Friend也实现Cloneable接口,并重写clone()方法,然后更改Person中的clone()方法。 :clone方法将对象复制了一份并返回给调用者。一般而言,clone()方法满足 对任何的对象x,都有x.clone() !=x 因为克隆对象与原对象不是同一个对象对任何的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。





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

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

相关文章

二、8.系统调用、可变参数和堆内存管理

系统调用:让用户进程申请操作系统的帮助 一个系统功能调用分为两部分, 一部分是暴露给用户进程的接口函数,它属于用户空间,此部分只是用户进程使用系统调用的途径,只负责发需求。另一部分是与之对应的内核具体实现&am…

记一次oracle数据库迁移至mysql数据库(表同步)

目录 一、利用Navicat将oracle迁移至mysql数据库 1、建立数据传输 2、选择需要迁移的数据库跟目标库 3、数据传输选项 4、选择需要迁移表信息 二、迁移之后遇到的一些问题 1、大小写问题 2、数据库函数问题 3、sql语句是否使用空格隔开问题 4、关于子查询别命名问题 …

SpringMVC-2-Spring MVC拦截器详解:从入门到精通

SpringMVC-2-Spring MVC拦截器详解:从入门到精通 今日目标 能够编写拦截器并配置拦截器 1.拦截器【理解】 1 拦截器介绍 1.1 拦截器概念和作用 拦截器(Interceptor)是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方…

SOFARPC(笔记)

文章目录 一、快速开始1.1 SOFARPC1.2 基于SOFABoot 二、注册中心三、通讯协议2.1 Bolt基本发布调用方式超时控制协议泛化调用序列化协议自定义线程池 2.2 RESTful基本使用 2.3 其他协议四、架构 附录 官方样例下载地址-sofa-boot-guides 可查看 SOFARPC 方式快速入门 一、快…

Elasticsearch(十二)搜索---搜索匹配功能③--布尔查询及filter查询原理

一、前言 本节主要学习ES匹配查询中的布尔查询以及布尔查询中比较特殊的filter查询及其原理。 复合搜索,顾名思义是一种在一个搜索语句中包含一种或多种搜索子句的搜索。 布尔查询是常用的复合查询,它把多个子查询组合成一个布尔表达式,这些…

docker安装clickhouse

安装 docker安装 创建clickhouse目录 mkdir -P /data/clickhouse/datamkdir -P /data/clickhouse/confmkdir -P /data/clickhouse/log 拉取镜像 这里直接拉取最新镜像, 如果需要某个特定版本, 则再拉取的时候指定版本号即可. docker pull clickhouse/clickhouse-server 启动临…

最新AI系统ChatGPT网站程序源码/搭建教程/支持GPT4.0/Dall-E2绘画/支持MJ以图生图/H5端/自定义训练知识库

一、正文 SparkAi系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。 那么如何搭建部署AI创作ChatGPT?小编这里写一个详细图文教程吧&#xff01…

Redis系列(四):哨兵机制详解

首发博客地址 https://blog.zysicyj.top/ 前面我们说过,redis采用了读写分离的方式实现高可靠。后面我们说了,为了防止主节点压力过大,优化成了主-从-从模式 思考一个问题,主节点此时挂了怎么办 这里主从模式下涉及到的几个问题&a…

华为OD-整数对最小和

题目描述 给定两个整数数组array1、array2,数组元素按升序排列。假设从array1、array2中分别取出一个元素可构成一对元素,现在需要取出k对元素,并对取出的所有元素求和,计算和的最小值 代码实现 # coding:utf-8 class Solution:…

ISVE2023展商 | 皮克智能:零售及互联网领域数字化变革开拓者

ISVE2023展商 | 皮克智能:零售及互联网领域数字化变革开拓者 01 公司介绍 Exhibitor Profile 皮克智能是优质的智能硬件产品及系统解决方案提供商,具备自主研发创新、软硬件方案集成及全产业链资源整合的能力。 公司总部位于中国深圳,主要服…

小程序中通过canvas生成并保存图片

1. html <canvas class"canvas" id"photo" type"2d" style"width:200px;height: 300px;"></canvas> <button bindtap"saveImage">保存</button> <!-- 用来展示生成的那张图片 --> <image…

构建 NodeJS 影院预订微服务并使用 docker 部署(03/4)

一、说明 构建一个微服务的电影网站&#xff0c;需要Docker、NodeJS、MongoDB&#xff0c;这样的案例您见过吗&#xff1f;如果对此有兴趣&#xff0c;您就继续往下看吧。 你好社区&#xff0c;这是&#x1f3f0;“构建 NodeJS 影院微服务”系列的第三篇文章。本系列文章演示了…

Ae 效果:CC Line Sweep

过渡/CC Line Sweep Transition/CC Line Sweep CC Line Sweep&#xff08;CC 线条扫描&#xff09;通过线条的扫描动作来制作一个过渡效果&#xff0c;线条可以根据设定的方向、厚度、倾斜度和方向翻转来扫过画面&#xff0c;从而将一个场景过渡到另一个。 ◆ ◆ ◆ 效果属性…

数据治理核心知识点总结-1

管理数据的人员必须由业务人员和信息技术人员两类角色共同承担&#xff1b; 数据管理的12个原则&#xff0c;这12个原则分为数据管理原则、数据价值、数据管理需求是业务的需求、数据管理依赖于不同的技能&#xff0c;数据管理是生命周期管理5个方面&#xff1b;这5个方面中&am…

6-3 使用函数输出水仙花数

分数 20 全屏浏览题目 切换布局 作者 张高燕 单位 浙大城市学院 水仙花数是指一个N位正整数&#xff08;N≥3&#xff09;&#xff0c;它的每个位上的数字的N次幂之和等于它本身。例如&#xff1a;153135333。 本题要求编写两个函数&#xff0c;一个判断给定整数是否水仙花数…

深度学习-实验1

一、Pytorch基本操作考察&#xff08;平台课专业课&#xff09; 使用&#x1d413;&#x1d41e;&#x1d427;&#x1d42c;&#x1d428;&#x1d42b;初始化一个 &#x1d7cf;&#x1d7d1;的矩阵 &#x1d474;和一个 &#x1d7d0;&#x1d7cf;的矩阵 &#x1d475;&am…

node配合charles写文件并下载

利用charles的Copy URL 和Copy cURL Request 进行抓取喜马拉雅的m4a文件 将抓取的下载链接粘贴进txt,利用如下代码去重,并生成新的sh文件,执行sh文件即可下载 const fs require("fs");//need config const inputFile "input.txt"; const outputFile &q…

JCTools Mpsc源码详解(一)

Jctools介绍--jctools是一个Java开源并发非阻塞数据结构实现,其中主要实现了非阻塞Map和非阻塞queue,旨在为Java提供高性能并发数据结构实现; jctool的特点--为什么性能高: lazyset--putOrderedObject,使用loadload内存屏障,写不会立即可见大量的位运算伪共享-通过pad类实现内…

嵌入式系统中常见内存的划分方法

看到有小伙伴在讨论关于单片机内存的话题&#xff0c;今天就结合STM32给大家描述一下常见的划分区域。 在一个STM32程序代码中&#xff0c;从内存高地址到内存低地址&#xff0c;依次分布着栈区、堆区、全局区&#xff08;静态区&#xff09;、常量区、代码区&#xff0c;其中全…

npm install 安装依赖,报错 Host key verification failed

设置 git 的身份和邮箱 git config --global user.name "你的名字" > 用户名 git config --global user.email “你的邮箱" > 邮箱进入 > 用户 > [你的用户名] > .ssh文件夹下,删除 known_hosts 文件即可 进入之后有可能会看到 known_hosts…