1.Cloneable接口的作用
Cloneable是标记接口(其方法体为空),它用来表示一个类拥有某些希望具有的特征。实现Cloneable接口的类被标记为可克隆的,而且其对象可以使用Object类中定义的clone()方法克隆。如果没有实现Cloneable类对象,调用clone()就回抛出CloneNotSupportedException异常
java.lang包中的 Cloneable 接口的定义如下所示:
package java.lang
public interface Cloneable{
}
2.克隆(复制)的分类
a.浅复制
b.深复制
如果一个数据类型是基本类型,复制的就是它的值。如果一个数据域是对象,复制的就是该域的引用。
下面通过一个类来演示Cloneable接口的用法,以及深、浅复制区别
public class House implements Cloneable,Comparable<House>{
private int id;
private double area;
java.util.Date whenBuilt;
public House(int id, double area){
this.id = id;
this.area = area;
whenBuilt = new java.util.Date();
}
public int getId() {
return id;
}
public double getArea(){
return area;
}
public java.util.Date getWhenBuilt(){
return whenBuilt;
}
@Override
/*浅复制*/
public Object clone(){
try{
return super.clone();
}
catch (CloneNotSupportedException ex){
return null;
}
}
/*深复制*/
// public Object clone(){
// try{
// //Perform a shallow copy
// House houseClone = (House)super.clone();
// //Deep copy on whenBuilt
// houseClone.whenBuilt = (java.util.Date)(whenBuilt.clone());
// return houseClone;
// }
// catch (CloneNotSupportedException ex){
// return null;
// }
// }
@Override
public int compareTo(House o){
if(area > o.area)
return 1;
else if(area<o.area)
return -1;
else
return 0;
}
}
测试类代码、
public class HouseTest {
public static void main(String[] args){
House house1 = new House(1,888);
House house2 = (House)house1.clone();
System.out.println("* * * * * * * * * * * * * * * * * * * * * * *");
System.out.println("house1 = house2? "+ house1.equals(house2));
if(house1.whenBuilt == house2.whenBuilt)
System.out.println("浅复制");
else
System.out.println("深复制");
System.out.println("* * * * * * * * * * * * * * * * * * * * * * *");
}
}
house1和house2是两个内容相同的不同对象。Object类中的clone()方法将原始对象的每个数据域复制给目标对象。
尽管house1 == house2为假,但是house1.whenBulit == house2.whenBuilt为真。这就是浅复制而不是深复制,这意味着如果数据域是对象类型,那么复制的是对象的引用,而不是他的内容。
* * * * * * * * * * * * * * * * * * * * * * *
house1 = house2? false
浅复制
* * * * * * * * * * * * * * * * * * * * * * *
如果希望House对象执行深复制,将clone()方法中的代码换成被注解的部分。这时候house1.whenBulit == house2.whenBuilt为假。house1和house2包含两个不同的Date对象
* * * * * * * * * * * * * * * * * * * * * * *
house1 = house2? false
深复制
* * * * * * * * * * * * * * * * * * * * * * *
3. clone方法和 Cloneable接口引发的思考
其一,为什么Object类中的clone方法定义为protected,而不是public?
因为不是每个对象都可以被克隆的。Java的设计者故意强制子类在其对象可克隆的情况下重写表方法。
其二,为什么clone方法不是定义在Cloneable接口中呢?
因为Java提供了一个本地方法来执行一个浅复制以克隆一个对象。由于接口中的方法是抽象的,该本地方法不能在接口中实现。因此,Java的设计者决定在Object类中定义和实现本地clone方法。
其三,为什么0bject类不实现Cloneable接口呢?
答案和第一个问题一样。
其四,House类不实现Cloneable,将会发生什么?
house1. clone()将返回null.