Java 对象的克隆Clone和必须了解的浅拷贝与深拷贝

public String toString() {

return “Sheep{” +

“name='” + name + ‘’’ +

“, age=” + age +

‘}’;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Integer getAge() {

return age;

}

public void setAge(Integer age) {

this.age = age;

}

}

仅到此,我们来写个测试方法,试一下克隆一个sheep对象,生成 sheep2对象:

public static void main(String[] args) throws CloneNotSupportedException {

Sheep sheep=new Sheep();

sheep.setName(“merry”);

sheep.setAge(5);

System.out.println(“克隆前 sheep :”+sheep.toString());

System.out.println(“-----进行克隆-----”);

Sheep sheep2 = (Sheep) sheep.clone();

System.out.println(“克隆出来的 sheep2:” +sheep2.toString());

System.out.println("sheep 与 sheep2 的内存地址是否一样 : "+ (sheep2==sheep));

sheep2.setName(" update from sheep2");

System.out.println(“修改 sheep2 的name后, sheep:”+sheep.toString());

System.out.println(“修改 sheep2 的name后, sheep2:”+sheep2.toString());

}

可以看到结果:

到这里是否就认为clone的使用就这样子ok了呢?

确实,如果你需要进行克隆的对象里面,只包含基本变量的话,这种clone的使用确实已经足够了。

但是如果里面包含的不只是基本变量,还存在其他对象的引用,那么就涉及到了深拷贝与浅拷贝的知识。

注意注意注意,当对象内包含其他对象的引用, clone 克隆出来的对象,并没有真正的实现数据克隆! 这就是使用clone需要考虑的深浅拷贝问题!

深拷贝  与  浅拷贝

在我们结合代码实例前,我们先了解下这个深拷贝,浅拷贝的概念理论知识:

浅拷贝: 指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。

深拷贝 :深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。

这么一看,是不是发现了我们上面的例子里面,其实就是属于浅拷贝,确实如此。

因为对于clone方法来说,

如果不对clone()方法进行改造,那么默认的使用,都是浅拷贝。

结合实例:

可见现在的sheep类里已经除了基本变量还包含了额外的对象引用 Wool

Wool.java

那么基于这种情况,我们来试试此时浅拷贝克隆出来的情景:

public static void main(String[] args) throws CloneNotSupportedException {

Wool wool=new Wool();

wool.setColor(“Red Red Red Red”);

Sheep sheep=new Sheep();

sheep.setName(“merry”);

sheep.setAge(5);

sheep.setWool(wool);

System.out.println(“克隆前 sheep :”+sheep.toString());

System.out.println(“-----进行克隆-----”);

Sheep sheep2 = (Sheep) sheep.clone();

System.out.println(“克隆出来的 sheep2:” +sheep2.toString());

System.out.println(“------对sheep2的Wool 颜色属性进行修改------”);

sheep2.getWool().setColor(“Black Black Black”);

System.out.println(“修改 wool颜色后, sheep:”+sheep.toString());

System.out.println(“修改 wool颜色后, sheep2:”+sheep2.toString());

}

结果:

为什么?

因为这是浅度拷贝,对除了基本变量的属性值复制外,对里面的wool对象引用并没有额外分配新的内存地址,所以一旦修改了wool,无论是修改sheep的wool属性还是sheep2的属性, 都会致使 使用到wool对象的对象实例 受影响。

所以对于这种实例里面包含了其他对象的引用,在我们使用克隆clone方法时,我们需要对clone()进行改造,实现深拷贝。

这样不管后续怎么去修改,克隆出来的对象与被克隆的对象都互不干扰。

进行改造,如上面的分析,我们需要在对Sheep进行克隆的时候,对里面的Wool也分配新的内存地址。

所以:

改造步骤1,让Wool也实现Cloneable,里面wool的重写的clone方法来进行新的内存地址划分。

改造步骤2,在Sheep的clone方法里,调用wool的clone方法然后再赋值。

具体代码:

步骤1

Wool.java

public class Wool implements Cloneable{

private String color;

@Override

protected Object clone() throws CloneNotSupportedException {

return super.clone();

}

@Override

public String toString() {

return “Wool{” +

“color='” + color + ‘’’ +

‘}’;

}

public String getColor() {

return color;

}

public void setColor(String color) {

this.color = color;

}

}

步骤2:

Sheep.java

public class Sheep implements Cloneable {

private String name;

private Integer age;

private Wool wool;

@Override

public Object clone() throws CloneNotSupportedException {

Sheep sheep= (Sheep) super.clone();

sheep.wool= (Wool) wool.clone();

return sheep;

}

@Override

public String toString() {

return “Sheep{” +

“name='” + name + ‘’’ +

“, age=” + age +

“, wool=” + wool +

‘}’;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public Integer getAge() {

return age;

}

public void setAge(Integer age) {

this.age = age;

}

public Wool getWool() {

return wool;

}

public void setWool(Wool wool) {

this.wool = wool;

}

}

Sheep的clone方法改造分析:

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
24年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

[外链图片转存中…(img-rwwqdBsg-1715705235575)]

[外链图片转存中…(img-4vBygjKr-1715705235576)]

[外链图片转存中…(img-KyzGkw2g-1715705235576)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 24
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值