Java之Clonable接口和深浅拷贝

news2024/11/29 12:41:42

Clonable接口

我们船舰了一个人的对象,想要克隆一个一模一样的对象,可以用到object类里面的克隆方法

object不是所有类的父类吗?那为什么用person1点不出这个方法呢?可以看一下源码

这是Object类里面的clone方法的声明,native说明这是本地方法,底层是由c/c++实现的。注意,它的访问权限是protected,所以再不同包中的子类只可以用super来引用,但super又不能静态方法中使用,所以我们只能再Person类里面重写一个方法,如下:

但还是报错,注意throws CloneNotSupportedException表示克隆不支持异常,语法规定,我们需要在main方法后面也加上这一句,同时,clone方法的返回值是Object类型,但在main方法中我们用了它的子类来接收,这是向下转型,必须要用括号强转,如下:

但还是报错,这就是 CloneNotSupportedException,即不支持克隆,那么这时,Clonable接口就起作用了,我们需要让那个被克隆的类去实现Clonable接口,如下:

空接口/标记接口

我们再看一下接口的源码:

发现里面没有任何抽象方法,这就是一个空接口或者叫标记接口,表示该类可以被拿去克隆

将上面的错误全部修正后,person1就可以被克隆了

深拷贝与浅拷贝

现在,我们再在person类里面加一个成员变量money,它是Money类的

class Money{

    public double m=29.9;
    
}
class Person implements Cloneable{
    public String name;
    public int age;
    public Money money=new Money();
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Test {
    public static void main(String[] args)throws CloneNotSupportedException  {
        Person person1=new Person("张三",20);
        Person person2=(Person)person1.clone();
        System.out.println("person1:"+person1.money.m);
        System.out.println("person1:"+person2.money.m);
        System.out.println("==========");
        person1.money.m=99.9;
        System.out.println("person1:"+person1.money.m);
        System.out.println("person1:"+person2.money.m);
        
        
    }
}

如上,那输出的结果是什么?

浅拷贝

按理说,即使person2是克隆出来的,但它也是一个独立的个体,应该不会受person1的影响,可却出现了上面的现象,实际上,在拷贝money时,由于money是个引用类型,它的值是所指对象的地址,在拷贝时,就将person1的money的值直接给到了person2的money,导致两个money都指向了同一个对象,而不是我们想看到的不是同一个对象而只是有一样的值罢了。

这种对于money的拷贝就是浅拷贝

深拷贝

那如何进行深拷贝?其实就是再给person2的money另外开辟一块空间,然后再将person1的money所指对象的值拷贝到person2的money所指对象。既然要克隆money,那么就要让money也支持克隆,如下

第二张图的第二行代码是刚刚的浅拷贝,在它的基础上再将money也拷贝一份,就能实现真正意义上的一式两份,也就是深拷贝。那么我们如何将二三行代码合在一起?先看一下重写的克隆方法:

这个方法是放在哪个类就克隆哪个类,由于在person类里面重写的clone方法仅支持person的克隆,所以我们可以修改这个克隆方法使他还可以将内部的money也克隆一份,而不仅仅是克隆其表面的值,如下:

可是,这个代码有很大的问题,当我们用this.clone时,就会出现死循环,一i那位这是自己调用了自己,所以应该修改为用Object类的clone方法,即用到super,如下:

这时修改1的值就不会影响2了

最终代码就是

class Money implements Cloneable{
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public double m=29.9;

}
class Person implements Cloneable{
    public String name;
    public int age;
    public Money money=new Money();
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
       Person tmp=(Person) super.clone();
       Money money=(Money) this.money.clone();
       tmp.money=money;
       return tmp;
    }
}
public class Test {
    public static void main(String[] args)throws CloneNotSupportedException  {
        Person person1=new Person("张三",20);
        Person person2=(Person)person1.clone();
        //person2.money= (Money) person1.money.clone();
        System.out.println("person1:"+person1.money.m);
        System.out.println("person2:"+person2.money.m);
        System.out.println("==========");
        person1.money.m=99.9;
        System.out.println("person1:"+person1.money.m);
        System.out.println("person2:"+person2.money.m);

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

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

相关文章

随机游走Python中的实现

随机游走是一个数学对象,称为随机或随机过程,它描述了一条路径,该路径由一些数学空间(如整数)上的一系列随机步骤组成。随机游走的一个基本例子是整数线上的随机游走,它从0开始,每一步以相等的概…

docker小白第五天

docker小白第五天 docker的私有库 有些涉密的信息代码不能放在阿里云的镜像仓库,因此需要构建一个个人内网专属的私有库,将镜像或者容器代码进行推送保存。 下载镜像docker registry 执行代码docker pull registry,用于搭建私服前的准备。…

为什么选择计算机?大数据时代学习计算机的价值探讨

还记得当初自己为什么选择计算机? 计算机是在90年代兴起的专业,那时候的年轻人有驾照、懂外语、懂计算机是很时髦的事情! 当初你问我为什么选择计算机,我笑着回答:“因为我梦想成为神奇的码农!我想像编织魔法一样编写程序,创造出炫酷的虚拟世界!”谁知道,我刚入门的…

力扣刷题-二叉树-平衡二叉树

110 平衡二叉树 给定一个二叉树,判断它是否是高度平衡的二叉树。 本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。 示例 1: 给定二叉树 [3,9,20,null,null,15,7] 返回 true 。 给定二叉树 [1…

diffuser为pipeline设置不用的scheduler

查看默认的schedulers: 使用默认的schedulers生成数据 查看默认scheduler的默认配置,定义了采样器中的相关参数,网上关于DDPM和DDIM的文章较多,可以先去看看这两种schedulers: 修改scheduler,可以用于…

【TB作品】51单片机,具有报时报温功能的电子钟

2.具有报时报温功能的电子钟 一、功能要求: 1.显示室温。 2.具有实时时间显示。 3.具有实时年月日显示和校对功能。 4.具有整点语音播报时间和温度功能。 5.定闹功能,闹钟音乐可选。 6.操作简单、界面友好。 二、设计建议: 1.单片机自选(C51、STM32或其他单片机)。 2.时钟日历芯…

【已解决】每次点击Windows 10 任务栏会闪退

一台装有 Windows 10 系统的电脑,最近通过“Windows 易升”升级到22H2版之后出现一个兼容问题:每次鼠标点击任务栏切换其他程序,任务栏都会闪退,桌面图标消失,然后又恢复显示桌面图标以及任务栏程序。 这样每次切换其他…

社交网络分析3:社交网络隐私攻击、保护的基本概念和方法 + 去匿名化技术 + 推理攻击技术 + k-匿名 + 基于聚类的隐私保护算法

社交网络分析3:社交网络隐私攻击、保护的基本概念和方法 去匿名化技术 推理攻击技术 k-匿名 基于聚类的隐私保护算法 写在最前面社交网络隐私泄露用户数据暴露的途径复杂行为的隐私风险技术发展带来的隐私挑战经济利益与数据售卖防范措施 社交网络 用户数据隐私…

【气候模式降尺度】分位数增量映射(QDM)原理及MATLAB代码实现

分位数增量映射(quantile delta mapping, QDM) 1 QDM偏差订正原理2 MATLAB实现代码3 案例参考气候模式的模拟结果与观测数据往往存在着一定的系统偏差,若将气候模式结果直接应用于作物模型或者水文模型中,其偏差会对模拟产生很大的影响,因此需要对气候模拟结果进行误差订正…

C++初阶-queue的使用与模拟实现

queue的使用与模拟实现 一、queue的介绍和使用二、queue的使用三、queue的模拟实现3.1 成员变量3.2 成员函数3.2.1 push入队列3.2.2 pop出队列3.2.3 返回队头数据3.2.4 返回队尾数据3.2.5 返回队列的大小3.2.6 判断队列是否为空 四、完整代码4.1 queue.h4.2 test.h 五、deque的…

new一个对象

1.自己直接调用 function Person(name, age) {this.name name;this.age age;}let a1 new Person("小明", 20);let a2 new Person("小菜", 25);console.log(a1); 打印的对象: 2.自己模拟一个 function Person(name, age) {this.name name;this.age a…

计算机网络:网络层(无分类编址CIDR、计算题讲解)

带你快速通关期末 文章目录 前言一、无分类编址CIDR简介二、构成超网三、最长前缀匹配总结 前言 我们在前面知道了分类地址,但是分类地址又有很多缺陷: B类地址很快将分配完毕!路由表中的项目急剧增长! 一、无分类编址CIDR简介 无分类域间路由选择CI…

Java多线程编程学习

1 线程的概念 多线程是指同一个程序同时存在多个“执行体”,它们可以同时工作 1.1 进程的概念 一次程序的每一次运行都叫做进程(一个进程可以包含多个线程 1.2 线程的概念 多线程是指一个程序中多段代码同时并发进行 1.3 主线程的概念 JavaMain中的线程就…

C语言——预处理详解(#define用法+注意事项)

#define 语法规定 #define定义标识符 语法: #define name stuff #define例子 #include<stdio.h> #define A 100 #define STR "abc" #define FOR for(;;)int main() {printf("%d\n", A);printf("%s\n", STR);FOR;return 0; } 运行结果…

机器学习算法---聚类

类别内容导航机器学习机器学习算法应用场景与评价指标机器学习算法—分类机器学习算法—回归机器学习算法—聚类机器学习算法—异常检测机器学习算法—时间序列数据可视化数据可视化—折线图数据可视化—箱线图数据可视化—柱状图数据可视化—饼图、环形图、雷达图统计学检验箱…

SpringIOC之@Primary

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

自然语言处理阅读第二弹

HuggingFace 镜像网站模型库 NLP中的自回归模型和自编码模型 自回归&#xff1a;根据上文内容预测下一个可能的单词&#xff0c;或者根据下文预测上一个可能的单词。只能利用上文或者下文的信息&#xff0c;不能同时利用上文和下文的信息。自编码&#xff1a;对输入的句子随…

phpMyAdmin的常见安装位置

nginx的日志显示有人一直在尝试访问phpMyAdmin的setup.php&#xff0c;用了各种位置。 其实我只有一个nginx&#xff0c;别的什么也没有。 47.99.136.156 - - [01:44:37 0800] "GET http://abc.com:80/phpMyAdmin/scripts/setup.php HTTP/1.0" 404 162 "-"…

JUC并发编程 04——Java内存模型之JMM

一.CPU 缓存模型 为什么要弄一个 CPU 高速缓存呢&#xff1f; 类比我们开发网站后台系统使用的缓存&#xff08;比如 Redis&#xff09;是为了解决程序处理速度和访问常规关系型数据库速度不对等的问题。 CPU 缓存则是为了解决 CPU 处理速度和内存处理速度不对等的问题。 我们…

【redis,nosql】redis键值数据库

什么是redis数据库 Redis is an open source, in-memory data structure store used as a database, cache, message broker, and streaming engine. 存储模式 字符串&#xff08;String&#xff09; Redis strings store sequences of bytes, including text, serialize…