为什么你克隆了我,我却要随你而改变?
前言
想来大家应该会被标题吸引进来,但我顶真表示,对于初学Java的朋友们来说,尤其是学到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不变。person1和person2都指向着money,所以之后修改money的值之后输出的值都为7.
出现这样的结果并非clone
有局限性,而是程序员没有更好的运用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();
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想要如何使用完全取决于程序员自己。
转载自:https://juejin.cn/post/7344991898623180850