概述
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象
场景
游戏存档
对于复杂对象,已存在一个实例时创建新的实例
实现
被克隆的类需要继承Cloneable接口并重写clone方法
浅克隆
/**
* 被克隆对象
*/
public class BeCloneBean implements Cloneable{
public String name;
public String loc;
public int age;
public AnotherBean anotherBean;
public BeCloneBean(String name, String loc, int age, AnotherBean anotherBean) {
this.name = name;
this.loc = loc;
this.age = age;
this.anotherBean = anotherBean;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "BeCloneBean{" +
"name='" + name + '\'' +
", loc='" + loc + '\'' +
", age=" + age +
", anotherBean=" + anotherBean +
'}';
}
}
/**
* 被克隆对象的一个成员
*/
public class AnotherBean {
public String name;
public int age;
public AnotherBean(String name, int age) {
this.name = name;
this.age = age;
}
}
/**
* 测试浅克隆
* @throws CloneNotSupportedException
*/
@Test
public void testShallowClone() throws CloneNotSupportedException {
AnotherBean anotherBean = new AnotherBean("weic",18);
BeCloneBean beCloneBean = new BeCloneBean("weicheng","fujian",18,anotherBean);
BeCloneBean clone = (BeCloneBean)beCloneBean.clone();
System.out.println(beCloneBean == clone);
System.out.println(beCloneBean.anotherBean == clone.anotherBean);
System.out.println("------------------------------------------");
System.out.println(beCloneBean.name == clone.name);
beCloneBean.name="aaa";
System.out.println(clone.name);
}
浅克隆执行结果:
深克隆
/**
* 被克隆对象
*/
public class BeCloneBean implements Cloneable{
public String name;
public String loc;
public int age;
public AnotherBean anotherBean;
public BeCloneBean(String name, String loc, int age, AnotherBean anotherBean) {
this.name = name;
this.loc = loc;
this.age = age;
this.anotherBean = anotherBean;
}
@Override
protected Object clone() throws CloneNotSupportedException {
BeCloneBean clone =(BeCloneBean)super.clone();
clone.anotherBean = (AnotherBean) clone.anotherBean.clone();
return clone;
}
@Override
public String toString() {
return "BeCloneBean{" +
"name='" + name + '\'' +
", loc='" + loc + '\'' +
", age=" + age +
", anotherBean=" + anotherBean +
'}';
}
}
/**
* 被克隆对象的一个成员
*/
public class AnotherBean implements Cloneable {
public String name;
public int age;
public AnotherBean(String name, int age) {
this.name = name;
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
/**
* 测试深度克隆
* @throws CloneNotSupportedException
*/
@Test
public void testDeepClone() throws CloneNotSupportedException {
AnotherBean anotherBean = new AnotherBean("weic",18);
BeCloneBean beCloneBean = new BeCloneBean("weicheng","fujian",18,anotherBean);
BeCloneBean clone = (BeCloneBean)beCloneBean.clone();
System.out.println(beCloneBean == clone);
System.out.println("------------------------------------------");
System.out.println(beCloneBean.anotherBean == clone.anotherBean);
}
深克隆执行结果:
总结
1.浅克隆:只有被克隆的对象实现Cloneable接口重写clone方法,这种方式只能克隆基本类型数据,克隆前后引用型的属性还是指向同一个对象;
2.深克隆:被克隆对象及其内部其他对象类型都实现Cloneable接口,重写clone方法,这种方式克隆前后包括内部引用型属性都是不同的对象;
3.String类型说明:String类型被克隆后两个对象的String引用都指向字符串常量池的同一个常量,因此他们是同一个对象,但是当改变其中一个对象String的值的时候此String类型引用将指向另一个内存空间,因此不会影响其他的克隆对象。