复制:将某个对象的引用复制给另一个对象,两个对象还是指向同一个应用。
克隆:分为浅复制、深复制。
浅复制:将对象的数据进行复制,但是对象中包含的对象,仍旧只是复制对象的引用。
深复制:不仅复制对象的基本类型属性,对于对象中包含的对象的数据也进行复制。
要实现克隆,需要重写Object的访问权限protected的clone方法。
既然Object是所有类的超类,为什么不能直接调用clone方法?
这是由于protected受访问保护规则是很微妙的。虽然protected域对所有子类都可见。但是有一点很重要,子类只能在自己的作用范围内访问自己继承的那个父类protected,而无法到访问别的子类(同父类的亲兄弟)所继承的protected域和父类对象的protected域。所以需要在子类重写clone方法,并且访问权限设置为public,才能被其他类调用。
注意:重写clone方法,所在类必须实现Cloneable标识接口,作为克隆的标识,否则会出现受检异常ClassNotSupportedException的问题。
class Person2 implements Cloneable{
private String name;
private int age;
private Date birthday = new Date();
public Person2(){
super();
}
public Person2(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(int year,int month,int day) {
Date newDay = new GregorianCalendar(year,month-1,day).getTime();
birthday.setTime(newDay.getTime());
}
public Person2 clone() throws CloneNotSupportedException{
Person2 cl = (Person2)super.clone();
cl.birthday = (Date)birthday.clone();
return cl;
}
public String toString(){
return name+":"+age+":"+birthday;
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person2 p = new Person2("原始",2);
p.setBirthday(2015, 2, 10);
Person2 copy = p.clone();
copy.setAge(3);
copy.setName("克隆");
copy.setBirthday(2016, 2, 10);
System.out.println("前 "+p);
System.out.println("后 "+copy);
}
}
浅复制和深复制的不同操作:在clone方法中,需不需要对子对象再次克隆。
浅复制:基本数据类型进行了数据复制,但是子对象仍旧是复制的引用
深复制:不仅基本数据类型进行了数据复制,子对象使用了克隆,进行了数据的复制,已经不再是引用的复制。