为什么你克隆了我,我却要随你而改变?

前言

想来大家应该会被标题吸引进来,但我顶真表示,对于初学Java的朋友们来说,尤其是学到clone的朋友来说物超所值。

  • 标题的意思理解起来就是本体被复制体所影响,要是各位还太能明白这句话的话,那么我将以代码的形式给各位聪明的大脑一点小小的点拨。

代码--浅拷贝

clone 复制代码
package InterFace;//Comparable
//主要知识点
//clone
class Money implements Cloneable{
    public double money = 3.5;

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

class Person implements Cloneable{
    public String name;
    public Money m;

    public Person(String name) {
        this.name = name;
        m = new Money();
    }

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

public class Test2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person("xiaowang");
        //将person1对象克隆为person2
        Person person2 = (Person) person1.clone();
        System.out.println("修改之前:" +person1.m.money);//3.5
        System.out.println("修改之前:" +person2.m.money);//3.5
        
        person2.m.money = 7;
        System.out.println("修改之后:" +person1.m.money);//?
        System.out.println("修改之后:" +person2.m.money);//?
        
        
    }
}

图上代码为简单的clone中我标出了两个"?",大家不妨思考一下输出的值为多少?

  • System.out.println("修改之后:" +person1.m.money);7

  • System.out.println("修改之后:" +person2.m.money);7

大家可能会认为person1.m.money的值为3.5 ,而person2.m.money的值为7 。 毕竟我们改变的是值是person2,也就是代码 person2.m.money = 7;。但从结果而言,person1却因为person2的值改变而改变了。这样的情况就是浅克隆。

图析

文字分析

1.假定person1 所处的地址为0X55 ,也能够看出name 的地址为0X55 (首地址----类似于数组),设定m 的地址为0X66

然后执行克隆语句,克隆之后,此时person2 的地址为0X11 ,复制后的name 地址则为0X11 ;而m 的地址仍为0X66 不变。person1person2 都指向着money ,所以之后修改money的值之后输出的值都为7.

出现这样的结果并非clone有局限性,而是程序员没有更好的运用clone方法。所以我们这里提出---深拷贝:完全拷贝出一个独立于原来对象的对象。

代码--深拷贝(由浅拷贝完善而来)

java 复制代码
class Person implements Cloneable{
    public String name;
    public Money m;

    public Person(String name) {
        this.name = name;
        m = new Money();
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        //return super.clone();
        Person tmp = (Person) super.clone();//创建局部变量接收 过程1
        tmp.m = (Money) this.m.clone();//克隆m   过程2
        return tmp;//将值送回person2

    }
}

浅转深拷贝的逻辑思路

想要解决无法拷贝完全的问题,就要回归起点,根据浅拷贝的最终结果展示,回归最初的问题---也就是

Person person2 = (Person) person1.clone();

这一语句错误的执行,没有将money进行拷贝。--那么我们就要重写clone方法。

  • 创建局部变量tmp来接收name。
  • 将m克隆出来
  • 返回给person2

此时代码的输出结果就为:

  • System.out.println("修改之后:" +person1.m.money);3.5

  • System.out.println("修改之后:" +person2.m.money);7

clone想要如何使用完全取决于程序员自己。

相关推荐
魔术师Grace3 小时前
从传统企业架构到 OPC 模式,AI 到底改变了什么?
人工智能·程序员
invicinble3 小时前
这里对java的知识体系做一个全域的介绍
java·开发语言·python
wbs_scy4 小时前
【Linux 线程进阶】进程 vs 线程资源划分 + 线程控制全详解
java·开发语言
ss2734 小时前
食谱推荐系统功能测试如何写?
java·数据库·spring boot·功能测试
AI人工智能+电脑小能手4 小时前
【大白话说Java面试题】【Java基础篇】第15题:JDK1.7中HashMap扩容为什么会发生死循环?如何解决
java·开发语言·数据结构·后端·面试·哈希算法
舒一笑4 小时前
我把设备指纹生成逻辑拆开了:它到底凭什么区分不同设备?
后端·程序员·掘金技术征文
try2find5 小时前
打印ascii码报错问题
java·linux·前端
014-code5 小时前
CompletableFuture 实战模板(超时、组合、异常链处理)
java·数据库
Nicander5 小时前
多数据源下@transcation事务踩坑
java·后端
それども5 小时前
DELETE 和 TRUNCATE TABLE区别
java·数据库·mysql