在Java中克隆分为两种:深度克隆和浅度克隆
-
浅度克隆:
浅度克隆完全复制一个对象,但对其内部的引用数据类型,浅度克隆只会复制该对象的引用,因此如果修改被克隆的对象,会影响到原对象。- 实现方式
1.被克隆的对象实现Cloneable接口,
2.让克隆的类重写Object的clone()方法
- 实现方式
-
深度克隆
深度克隆完全复制一个对象,包括原对象的引用数据类型也会复制并额外开辟空间去存储数据,独立于原对象,修改克隆出来的对象不会影响原对象。-实现方式
常用的是使用序列化实现深度克隆(比较常用,使用起来较为简单)。
浅度克隆例:
从下面的例子我们可以看出,浅度克隆中就会导致多个对象共享同一份资源。
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Eat eat = new Eat();
eat.setEat("小强吃");
//被克隆的对象
Pet1 pet1 = new Pet1();
pet1.setName("小强");
pet1.setEat(eat);
System.out.println(pet1.getName()+" "+pet1.getEat());输出内容:小强 小强吃
//克隆的对象
Pet1 pet2 = (Pet1)pet1.clone();
pet2.setName("小黑");
System.out.println(pet2.getName()+" "+pet2.getEat());输出内容:小黑 小强吃
eat.setEat("小黑吃");
pet2.setEat(eat);
System.out.println(pet1.getName()+" "+pet1.getEat());此时输出的对象变为了pet1,但是输出的内容为:小强 小黑吃
到这里就可以看出,浅克隆只克隆了引用,pet1和pet2共享同一个对象。
}
}
创建宠物类,实现Cloneable接口,标记Pet1是可被克隆的
class Pet1 implements Cloneable{
private String name;
private Eat eat;
public Eat getEat() {
return eat;
}
public void setEat(Eat eat) {
this.eat = eat;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
重写Object中的clone()方法
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
class Eat{
private String eat;
public String getEat() {
return eat;
}
public void setEat(String eat) {
this.eat = eat;
}
@Override
public String toString() {
return eat;
}
}
深度克隆例:
使用序列化