深/浅拷贝

news2024/11/24 6:25:21

现在有一个我们自定义的Person对象,如何去克隆这个对象?

class Person{
    public int id;

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                '}';
    }
}
public class Test2 {
    public static void main(String[] args) {
        Person person1 = new Person();
    }
}

1.给自定义的Person类实现Cloneable接口

class Person implements Cloneable{
    public int id;

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                '}';
    }
}

 2.重写Object克隆方法

class Person implements Cloneable{
    public int id;

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                '}';
    }

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

3. 声明异常,再进行强制类型转换

public class Test2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person();
        Person person2 = (Person) person1.clone();
    }
}

clone方法的返回值是Object,因此需要强制类型转换一下

浅拷贝

现在给这个 这个Person对象再添加一个NameAndMoney属性

class NameAndMoney{
    String name;
    double m;

    public NameAndMoney(String name, double m) {
        this.name = name;
        this.m = m;
    }

    @Override
    public String toString() {
        return "NameAndMoney{" +
                "name='" + name + '\'' +
                ", m=" + m +
                '}';
    }
}
class Person implements Cloneable{
    public int id;
    public NameAndMoney nameAndMoney;

    public Person(int id, String name,double m) {
        this.id = id;
        this.nameAndMoney = new NameAndMoney(name,m);
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", nameAndMoney=" + nameAndMoney +
                '}';
    }
}

浅拷贝:直接使用克隆方法

public class Test2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person(1,"张三",9999);
        Person person2 = (Person) person1.clone();
        person2.id=2;
        person2.nameAndMoney.name="李四";
        person2.nameAndMoney.m=8888;
        System.out.println(person1);
        System.out.println(person2);
    }
}

可以发现person2的改变会引起person1的变化,这就是浅拷贝,它只是把person1里面的内容完全复制了 

  也就是说只要0x11这个引用里面的内容发生改变,person1和person2都会发生改变

深拷贝

给NameAndMoney同样实现Cloneable接口,重写clone方法,再重写我们Person中的clone方法

class NameAndMoney implements Cloneable{
    String name;
    double m;

    public NameAndMoney(String name, double m) {
        this.name = name;
        this.m = m;
    }

    @Override
    public String toString() {
        return "NameAndMoney{" +
                "name='" + name + '\'' +
                ", m=" + m +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Person implements Cloneable{
    public int id;
    public NameAndMoney nameAndMoney;

    public Person(int id, String name,double m) {
        this.id = id;
        this.nameAndMoney = new NameAndMoney(name,m);
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person tmp = (Person) super.clone();
        tmp.nameAndMoney = (NameAndMoney)this.nameAndMoney.clone();
        return tmp;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", nameAndMoney=" + nameAndMoney +
                '}';
    }
}

 关键代码

 @Override
    protected Object clone() throws CloneNotSupportedException {
        Person tmp = (Person) super.clone();
        tmp.nameAndMoney = (NameAndMoney)this.nameAndMoney.clone();
        return tmp;
    }

 

 总结:

现在有a,b俩个对象,浅拷贝就相当于,b把a的内容完全复制,并赋予它新的地址,虽然这俩个引用的地址不同,但内容一样,如果这里面的内容有其他的引用,那此时a和b就共用了一个引用了,如果这个引用里面的内容发生修改,a和b都会发生改变.
可以把引用想象成一个壳子,b把a的壳子里面的内容复制到另一个壳子中,假如这个壳子里面包含了其它壳子,那么此时a和b就共用了这个它们共用的壳子,如果a或者b的任意一个改变了这个壳子里面的内容,此时a和b都会发生改变
深拷贝,就是b不是把a的内容完全复制,而是找出a里面还有哪些引用,并把这些引用的内容复制且赋予它们新的地址,这样a和b就不会有关联了
b不是把a里面的内容完全复制,而是找出a中还有哪些壳子,并把这些壳子里面的内容复制,然后给与这些壳子新的地址,这样a和b就不会指向同一个壳子了,有共用的壳子了

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

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

相关文章

ATFX国际:美国CPI骤降至3%,高通胀问题或不复存在

ATFX国际:美国通胀率数据搅动国际金融市场。6月未季调CPI年率,最新值3%,低于前值4%和预期值3.1%;6月未季调核心CPI年率,最新值4.8%,低于前值5.3%,低于预期值5%。名义CPI和核心CPI数据双双大降&a…

c++从源文件到可执行文件经历了什么

1.c从源文件到可执行文件经历了什么 在linux平台上 main.c —> a.out 在windows平台上 main.c --> xx.exe gcc -E main.c -o main.i // 预处理 gcc -S main.i -o main.s // 编译 gcc -c main.s -o main.o // 汇编 gcc main.o -o hello //链接

软件测试面试题 —— 整理与解析(3)

😏作者简介:博主是一位测试管理者,同时也是一名对外企业兼职讲师。 📡主页地址:🌎【Austin_zhai】🌏 🙆目的与景愿:旨在于能帮助更多的测试行业人员提升软硬技能&#xf…

Python的多线程编程-同步机制Lock实现

在Python的多线程编程中,为避免多个线程同时访问同一个共享资源而发生冲突,需要使用同步机制来确保线程安全,其中Lock就是一个同步机制。 Lock是一个互斥锁,当线程获取了锁,其他线程就不能再获取该锁,直到…

Redis_客户端命令和数据操作(3)

目录 切换数据库 键命令 数据结构 string类型 hash类型 list类型 set类型 zset类型 查看中文value 源码等资料获取方法 切换数据库 redis数据库没有名称,默认有16个,通过0-15来标识,连接redis默认选择第一个数据库,可以…

pytorch 中的执行模式

两种模式: PyTorch 支持两种执行模式:eager mode 和 graph mode。 E 模式,侧重于易用性与灵活性,适合科研人员,用于验证想法,魔改模型; G模式: 侧重于性能方面,适合生产,…

tomcat学习随笔

Tomcat结构与原理 一、组成ServerServiceConnectorProtocolHandlerEndpointProcessor Adaptor ContainerEngineHostContextWrapper 运行热部署jsp类war tomcat根路径目录结构示意图 一、组成 tomcat结构debug示意图 Server tomcat的实例,支持多个Service Service …

ChatGPT炒股:从股票招股说明书中批量提取竞争对手信息

股票招股说明书中都会提到上市公司的市场竞争情况和竞争对手。要研究企业,就必须仔细研究竞争对手。怎么将竞争对手这些信息批量从招股说明书中提取出来呢? 首先观察其规律: 有的是这样写的: 行业内的主要企业:浙江…

《Python机器学习:基于PyTorch和Scikit-Learn》——AIC松鼠活动第三期

内容简介 本书是一本全面介绍在PyTorch环境下学习机器学习和深度学习的综合指南,可以作为初学者的入门教程,也可以作为读者开发机器学习项目时的参考书。 本书讲解清晰、示例生动,深入介绍了机器学习方法的基础知识,不仅提供了构…

【广州华锐互动】疏通清洗车VR实训教学平台

疏通作业车是一种专门用于城市下水道、排水管道等清理和维护的特种车辆。由于其工作环境复杂,操作难度较大,因此需要专业的培训和技能掌握。为了提高疏通作业车驾驶员的技能水平,VR虚拟仿真技术应运而生。 VR虚拟仿真技术是一种通过计算机模…

记录jeecg-boot及a-table前端问题

标签页重复 原因: 在TabLayout中它有监听$route,是根据route.fullpath去判断的。这就会出现一种情况,我是同一个path比如/detail,但是我带了个参数/detail?id132165151651和/detail?id256151561651这两个fullpath明显不同,所以…

ciscoNAT

静态NAT Router0 int f0/0 ip add 192.168.1.3 255.255.255.0 # 两个PC的网关 no shutdown int f0/1 ip add 202.103.224.1 255.255.255.0 no shutdown exit ip route 0.0.0.0 0.0.0.0 202.103.224.2 # 配置默认路由能够去往目标网络 # 将内部网络的IP地址(192.168.1.1)映射到…

Typora 免费版下载安装(超简单亲测适用于Windows)与入门

前言 Typora大家都知道, 是一款好用的编辑器和阅读器。鬼鬼为大家找了一个可使用版本,安装过程十分简单,亲测有效,不浪费大家时间,现在将Typora分享给大家免费使用。下载链接在文章最后。 目录 前言 一、Typora的介…

前端JavaScript入门-day06

(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 作用域 局部作用域 全局作用域 作用域链 JS垃圾回收机制 1. 什么是垃圾回收机制 2.内存的生命周…

链路传播(Propagate)机制及使用场景

服务间链路追踪传播机制是指在微服务架构中,通过记录和跟踪服务之间的请求和响应信息,来实现对服务间链路的追踪和监控。这种机制可以帮助开发人员快速定位服务间出现的问题,并进行优化和调整。 具体来说,服务间链路追踪传播机制…

nvm的简介、安装、使用

一、nvm是什么? .nvm是一个node的版本管理工具,可以简单操作node版本的切换、安装、查看。。。等等,与npm不同的是,npm是依赖包的管理工具。 二、nvm的安装。 点击如下文件进行安装: (1)安装…

超声波功率放大器工作原理是什么意思

超声波功率放大器是一种能够将低功率、小振幅的超声波信号放大至足够高功率和大振幅输出的电子设备。它通常被用于超声波清洗、焊接、切割、医疗等领域中。 超声波功率放大器的工作原理基于声学共振的原理。具体来说,超声波功率放大器由一个压电陶瓷换能器和一个功放…

增强型(RX651)R5F56514EDFP、R5F5651EHDFP、R5F5651CDDBP微控制器,强化工业物联网安全。

RX651 微控制器 (MCU)系列产品,以满足工业自动化、楼宇自动化和智能表计系统更高的安全需求。扩展的微控制器集成了Trusted SecureIP(TSIP),以及用于工业和网络控制系统的增强型可靠闪存功能和人机界面(HMI&#xff0…

C# HTTP Error 500.19

解决办法&#xff1a; .vs configapplicationhost.config 修改<section name"windowsAuthenticationnurununoverrideModeDefault"Allow”/>

QQ消息是如何到达接收方的?看完这个你就明白了

A通过QQ给异地的B发了条消息&#xff0c;直到B收到了消息&#xff0c;中间经历了怎样的过程? 北京的A通过QQ给深圳的B发了一条消息&#xff0c;B在QQ上接收到了消息&#xff0c;从A点击发送开始&#xff0c;到B看到消息结束&#xff0c;中间过程是如何实现的&#xff1f;中间…