在解释什么是浅拷贝和深拷贝之前,我们来看一个例子吧~
浅拷贝:
package demo;
import java.util.ArrayList;
public class Thing implements Cloneable {
private ArrayList<String> arrayList = new ArrayList<>();
@Override
public Thing clone(){
Thing thing = null;
try {
thing = (Thing)super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return thing;
}
//设置HashMap的值
public void setValue(String value){
this.arrayList.add(value);
}
//取得arrayList的值
public ArrayList<String> getValue(){
return this.arrayList;
}
}
Thing类中私有一个arraylist,类型是ArrayList,然后通过get set分别进行设置和取值,我们来看下场景类:
package demo;
public class Client {
public static void main(String[] args){
//产生一个对象
Thing thing = new Thing();
//设置一个值
thing.setValue("张三");
//拷贝一个对象
Thing cloneThing = thing.clone();
cloneThing.setValue("李四");
System.out.println(thing.getValue());
}
}
结果如下:出乎人意料
[张三, 李四]怎么会有张三和李四呢?因为java做了一个偷懒的拷贝动作,Object类提供的clone方法只是拷贝本对象,其对象内部的数组引用对象都不拷贝,还是指向原生对象的内部元素地址,这种拷贝就叫做浅拷贝。其实是非常浅,两个对象共享了一个私有变量,你改我改的是一种非常不安全的方式,在实际项目中还是比较少的。 你可能在之前的原型模式中有点奇怪,为什么Mail这个类内部的String类型,不会产生浅拷贝带来的问题呢?内部的数组和引用对象才不拷贝,其他的原始类型比如:int,long,char都会被拷贝,但是对于String类型,java就希望你把它认为是基本类型,
它是没有clone方法的,处理机制也比较特殊,通过字符串stringpool在需要的时候才在内存中创建新的字符串,咱们在使用过程中就把String当作基本类来使用吧。
注意了使用原型模式时,引用的成员变量必须是满足两个条件才不会被拷贝:一个是类的成员变量,而不是方法内变量,二必须是一个可变的 引用对象,而不是一个原始类型或不可变的对象。
浅拷贝是有风险的,那么怎么才能深拷贝呢,我们修改一下上面的demo就可以了呢:
@Override
public Thing clone(){
Thing thing = null;
try {
thing = (Thing)super.clone();
<span style="color:#cc0000;">thing.arrayList = (ArrayList<String>)this.arrayList.clone();</span>
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return thing;
}Client不变,仅仅修改了红色部分,运行结果如下:
[张三]该方法就实现了完全拷贝,两个对象之间没有任何的瓜葛了,你修改你的我修改我的,不互相影响,这种拷贝就叫做深拷贝。深拷贝还有一种实现方式就是通过自己写二进制流来操作对象,然后实现对象的深拷贝。
深浅拷贝不建议混合使用,特别是在涉及类的继承时,父类有多个引用的情况下就非常复杂了,建议还是深浅拷贝分开来实现比较好。
还有关键的一点:要使用clone关键字,类的成员变量不要加final关键字!!!!!!!!
+一句原型模式可以这样理解的呢:一个对象的产生不可以由零起步,直接从一个已经具备一定雏形的对象克隆,然后再修改为生产需要的对象,也就是说,生产一个人,可以不从1岁开始,可以直接找一个人,获取DNA,然后克隆一个,直接修改一下30岁就可以了,我们讲的原型模式就是这样的功能。
1万+

被折叠的 条评论
为什么被折叠?



