1. Cloneable接口的作用
Cloneable是标记型的接口,它们内部都没有方法和属性,实现 Cloneable来表示该对象能被克隆,能使用Object.clone()方法。如果没有实现 Cloneable的类对象调用clone()就会抛出CloneNotSupportedException。
2. 克隆(拷贝)的分类
浅克隆(浅拷贝)(shallow clone),浅克隆是指拷贝对象时仅仅copy对象本身和对象中的基本变量,而不拷贝对象包含的引用指向的对象。
深克隆(深拷贝)(deep clone),不仅copy对象本身,而且copy对象包含的引用指向的所有对象。
举例:对象X中包含对Y的引用,Y中包含对Z的引用。浅拷贝X得到X1,X1中依然包含对Y的引用,Y中依然包含对Z的引用。深拷贝则是对浅拷贝的递归,深拷贝X得到X1,X1中包含对Y1(Y的copy)的引用,Y1中包含对Z1(Z的copy)的引用。
3. 克隆代码举例
要让对象可以被克隆,应具备以下2个条件:
- 让该类实现java.lang.Cloneable接口;
- 重写(Override)Object的clone()方法;
public class Dog implements Cloneable {
private Integer id;
private String name;
private BigDecimal weight;
private Food food;
public Dog(Integer id, String name, BigDecimal weight) {
this.id = id;
this.name = name;
this.weight = weight;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getWeight() {
return weight;
}
public void setWeight(BigDecimal weight) {
this.weight = weight;
}
public Food getFood() {
return food;
}
public void setFood(Food food) {
this.food = food;
}
@Override
public String toString() {
return "Dog{" +
"id=" + id +
", name='" + name + '\'' +
", weight=" + weight +
", food=" + food +
'}';
}
// 浅拷贝(使用时两者选其一)
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
// 深拷贝(使用时两者选其一)
@Override
protected Object clone() throws CloneNotSupportedException {
Object object = super.clone();
Food food = ((Dog) object).getFood();
((Dog) object).setFood((Food) food.clone());
return object;
}
}
引用对象:
public class Food implements Cloneable {
private String name;
public Food(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Food{" +
"name='" + name + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
测试代码:
public class DogTest {
// 测试浅拷贝
@Test
public void test() throws CloneNotSupportedException {
Dog jack = new Dog(18, "jack", BigDecimal.TEN);
Dog tom = (Dog) jack.clone();
tom.setId(19);
tom.setName("tom");
tom.setWeight(BigDecimal.ONE);
System.out.println(jack);
System.out.println(tom);
}
// 测试深拷贝
@Test
public void test2() throws CloneNotSupportedException {
Dog jack = new Dog(18, "jack", BigDecimal.TEN);
jack.setFood(new Food("冰淇淋"));
Dog tom = (Dog) jack.clone();
tom.setId(19);
tom.setName("tom");
tom.setWeight(BigDecimal.ONE);
tom.getFood().setName("三明治");
System.out.println(jack);
System.out.println(tom);
}
}