原型模式是指当某实例需要大量创建时,可以用克隆的方法对已有对象进行大量复制。因为Java的clone方法是利用C++再内存中直接复制对象的。所以不会执行新对象的构造方法
/**
* 被克隆对象
* */
public class Person implements Cloneable{
int i = 0;
String name = "xxx";
Location l = new Location();
@Override
public Object clone(){
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
/**
* 地址
* */
public class Location {
String location = "中国";
}
public class Main {
public static void main(String[] args) {
Person p = new Person();
Person pClone = (Person) p.clone();
}
}
如上,pClone就是Person对象p经过clone之后出来的对象
克隆过程中会涉及浅克隆和深克隆的问题。
Java底层默认为浅克隆,在克隆过程中引用类型指挥复制地址,这就导致复制后的多个对象内部的引用类型成员指向同一个对象
public class Main {
public static void main(String[] args) {
Person p = new Person();
Person pClone = (Person) p.clone();
System.out.println(pClone.l.location);
p.l.location = "美国";
System.out.println(pClone.l.location);
}
}
运行结果:
中国
美国
可以看到,虽然改变的是原始对象的引用类型成员中的值,但克隆对象的引用类型成员中的值也跟着变了。此时需要在重写clone方法时,将类内部的引用类型再克隆一次
/**
* 地址
* */
public class Location implements Cloneable{
String location = "中国";
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
/**
* 被克隆对象
* */
public class Person implements Cloneable{
int i = 0;
String name = "xxx";
Location l = new Location();
@Override
public Person clone(){
try {
Person p= (Person) super.clone();
p.l = (Location) p.l.clone();
return p;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
此时就解决了浅克隆的问题