1.Object类中有clone方法,但是Object又没有实现Cloneable接口,这是为什么?对于一个没有实现cloneable的类来说,还可以用从Object类继承而来的clone方法实现一些基本的值的复制操作,那是不是可以说clone方法并没有对对象是否属于Cloneable类型进行检验?
Object类的clone是protected的(
protected
Object
clone
() throws
CloneNotSupportedException),不能直接调用,可以被子类调用。Object类的clone会知道对象大小,为它分配足够的内存空间,并将旧对象的内容复制到新的对象中。但是Object.clone()执行其动作之前必须先检查class是否实现了Cloneable接口。
Cloneable接口是一个标记接口,也就是没有任何内容,定义如下。
package java.lang; public interface Cloneable{ }这里分析一下这接口的用法。
java中clone的含义是,假设X是一个非空对象,则:
1.x.clone() != x 为true,就是说它们不是同一个对象;
2.x.clone().getClass() == x.getClass()为true,说明它们是同一个类型class;
3.x.equals(x.clone())为true,说明逻辑上应当相当。
clone方法是在Object中定义的,而且是protected类型的,只有实现了这个接口,才可以在该类的实例上调用clone方法,否则会抛出
CloneNotSupportedException。
Object中默认的实现是一个浅复制,也就是表面复制,如果需要实现深层次的复制,必须对类中可变域生成新的实例。
public class Unsupported{ public Object clone(){ Object obj; try{ obj = supper.clone(); }catch(CloneNotSupportedException ex){ ex.printStackTrace(); } return obj; } }加上implements Cloneable就可以了。当然也可以不实现这个接口,但是覆盖clone方法,其代码如下:
public class Unnormal{ public Object clone(){ return new Unnormal(); } }这样肯定没问题的,不过已经和java中的clone机制没有关系了。
下面举一个例子说明浅复制和深复制。
public class ShallowCopy implements Cloneable{ private Date begin; public Date getBegin(){return this.begin;} public void setBegin(Date d){this.begin=d;} public Object clone(){ Object obj = null; try{ obj=super.clone(); }catch(CloneNotSupportedException ex){ ex.printStackTrace(); } return obj; } }
public class DeepCopy implements Cloneable{ private Date begin; public Date getBegin(){return this.begin;} public void setBegin(Date d){this.begin=d;} public Object clone(){ DeepCopy obj = null; try{ obj = (DeepCopy)super.clone(); }catch(CloneNotSupportedException ex){ ex.printStackTrace(); } obj.setBegin((Date)this.getBegin().clone()); return obj; } }
总结:
clone方法是在Object中定义的,而且是protected型的,只有实现了这个接口,才可以在该类的实例上调用clone方法,否则会抛出CloneNotSupportException。说clone方法并没有对对象是否属于cloneable类型进行检查这个观点是不正确的。因为cloneable接口的出现跟接口的正常使用没有任何关系,特别是它并不指定clone方法--------该方法从object类中继承而来,该接口只是作为一个标记。这句话通俗的说就是以下3点:首先,clone方法是Object类的一个方法,所以任何类都会自动拥有这一个方法。其次,这并不说明该类就可以调用clone了,因为Javac或者java需要程序员显示地指明该类可以调用clone,方法就是写上这个字符串”implements Cloneable“。再次,这个字符串只是起一个指示作用,没有其他功能,这是javac或者java的规定。