Prototype_原型模式
原型模式,就是拷贝,通过拷贝一个已经创建的原型实例,来创建一个和原型相同或相似的新对象。
Java中自带克隆方法,实现Cloneable接口,并重写clone方法。需要注意深拷贝和浅拷贝,默认方法是浅拷贝,即原型对象和克隆对象中的引用类型的对象所指向的地址值相同,都指向同一个对象,(就是克隆的时候是引用传递,不是值传递)。如果需要深拷贝可以通过改造clone方法,或通过序列化反序列化等方式来实现。
演示浅拷贝
- 实现Cloneable接口:这是一个标记性接口,里面没有需要我们实现的方法,不实现这个接口编译器不报错,但运行报错。
- 重写clone方法:Object对象中的clone方法是一个native方法,就是一个Java调用非Java代码的接口,clone方法是用C++写的,没有Java的原码,所有如果想使用clone方法必须重写clone方法。clone方法声明:
protected native Object clone() throws CloneNotSupportedException;
public class Person implements Cloneable{
public String name = "lin";
public Date date = new Date();
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "name: "+name+"\ndate: "+date+"\ndateHash: "+date.hashCode();
}
}
创建原型实例lin,并克隆出新实例copyLin。分别打印name,date,date的哈希值,实例的哈希值。
public static void main(String[] args) throws CloneNotSupportedException {
Person lin = new Person();
Person copyLin = (Person) lin.clone();
System.out.println(lin.toString() + "\nhashcode: "+lin.hashCode());
System.out.println(copyLin.toString() + "\nhashcode: "+copyLin.hashCode());
}
测试结果,实例的哈希值不一样,说明真的新建了实例,但Date引用的哈希值一样,说明并没有克隆出新的Date,属于浅拷贝。
通过改造clone方法实现深拷贝
在重写clone方法时,将对象的引用也进行克隆
@Override
protected Object clone() throws CloneNotSupportedException {
Person person = (Person) super.clone();
person.date = (Date) this.date.clone();
return person;
}
进行测试,克隆后修改了克隆实例引用的Date的值
public static void main(String[] args) throws CloneNotSupportedException {
Person lin = new Person();
Person copyLin = (Person) lin.clone();
copyLin.date.setTime(100000000);
System.out.println(lin.toString() + "\nhashcode: "+lin.hashCode());
System.out.println(copyLin.toString() + "\nhashcode: "+copyLin.hashCode());
}
结果只有克隆出来的实例的Date值被修改了,原型实例的Date值不变,说明是深克隆。
本文来自博客园,作者:独游空想家,转载请注明原文链接:https://www.cnblogs.com/linzhikai/p/16523052.html