java深浅克隆详解和标记接口Cloneable

文章资讯 2020-06-14 17:20:25

java深浅克隆详解和标记接口Cloneable

深克隆与浅克隆
一个对象的浅克隆是指,创建一个新对象,这个对象拥有原对象所有字段的一个副本。这样的浅克隆往往会造成一些问题。比如,当一个对象的某个字段,是另外一个可变对象的引用时,浅克隆仅仅为克隆对象复制了该子对象的引用,也就是说,克隆对象与原对象共享这个子对象。如上图所示,初始对象origin和克隆对象coy的hiDay字段指向同一个Date对象。
而对于深拷贝而言,要求一并深拷贝所有引用类型的字段,确保克隆对象和原对象不共享任何字段。这个过程可能是递归的,因为子对象也有可能拥有引用类型的字段。
在Java的Object类中定义了一个rotected的方法clone,
@HotSotIntrinsicCandidate
rotectednativeObjectclone()throwsCloneNotSuortedExcetion;该方法被native修饰,表名该方法是由其他语言实现的。
他采用的是简单的逐字段拷贝,也就是浅拷贝。并且,受限于rotected修饰符,clone方法并不能在你所定义的Object的子类外使用,关于rotected修饰符的作用,请参见我的另一篇博客:java权限修饰符(rotected):什么叫对包和子类可见
故若要向外提供一个clone方法,你必须要实现Cloneable接口,重写clone方法。
Cloneable接口
Cloneable接口是一个空接口,,也叫做标记接口。标记接口不包含任何方法;它的唯一作用是允许在类型查询中使用instanceof。如if(objisinstanceofCloneable)...用于判断目标对象是否是可克隆的。
需要注意的是,重写Object类的clone方法,必须实现Cloneable接口,不然的话会在程序运行时抛出CloneNotSuortedExcetion,尽管该接口什么方法也没有
所有的数组类型都有一个公共的clone方法,且不是rotected的,这意味着你可以在任何地方调用该方法。该方法将返回一个新数组,包含原数组中的所有元素的副本,它同样是浅复制的。
示例:
ublicclassMain{
ublicstaticvoidmain(String[]args){
varfs1=newFather[]{newFather(),newFather()};
varfs2=fs1.clone();
Syst.out.rintln(fs1==fs2);
Syst.out.rintln(fs1[0]==fs2[0]);
}
}