一、Object类中clone的实现。
二、clone详解。
看,clone()方法又是一个被声明为native的方法,因此,我们知道了clone()方法并不是Java的原生方法,具体的实现是有C/C++完成的。clone英文翻译为"克隆",其目的是创建并返回此对象的一个副本。形象点理解,这有一辆科鲁兹,你看着不错,想要个一模一样的。你调用此方法即可像变魔术一样变出一辆一模一样的科鲁兹出来。配置一样,长相一样。但从此刻起,原来的那辆科鲁兹如果进行了新的装饰,与你克隆出来的这辆科鲁兹没有任何关系了。你克隆出来的对象变不变完全在于你对克隆出来的科鲁兹有没有进行过什么操作了。Java术语表述为:clone函数返回的是一个引用,指向的是新的clone出来的对象,此对象与原对象分别占用不同的堆空间。
明白了clone的含义后,接下来看看如果调用clone()函数对象进行此克隆操作。
首先看一下下面的这个例子:
1 package com.corn.objectsummary; 2
3 import com.corn.Person; 4
5 public class ObjectTest { 6
7 public static void main(String[] args) { 8
9 Object o1 = new Object(); 10 // The method clone() from the type Object is not visible
11 Object clone = o1.clone(); 12 } 13
14 }
例子很简单,在main()方法中,new一个Oject对象后,想直接调用此对象的clone方法克隆一个对象,但是出现错误提示:"The method clone() from the type Object is not visible"
why? 根据提示,第一反应是ObjectTest类中定义的Oject对象无法访问其clone()方法。回到Object类中clone()方法的定义,可以看到其被声明为protected,估计问题就在这上面了,protected修饰的属性或方法表示:在同一个包内或者不同包的子类可以访问。显然,Object类与ObjectTest类在不同的包中,但是ObjectTest继承自Object,是Object类的子类,于是,现在却出现子类中通过Object引用不能访问protected方法,原因在于对"不同包中的子类可以访问"没有正确理解。
"不同包中的子类可以访问",是指当两个类不在同一个包中的时候,继承自父类的子类内部且主调(调用者)为子类的引用时才能访问父类用protected修饰的成员(属性/方法)。 在子类内部,主调为父类的引用时并不能访问此protected修饰的成员。!(super关键字除外)
于是,上例改成如下形式,我们发现,可以正常编译:
1 package com.corn.objectsummary; 2
3
4 public class ObjectTest { 5
6 public static void main(String[] args) { 7 ObjectTest ot1 = new ObjectTest(); 8
9 try { 10 ObjectTest ot2 = (ObjectTest) ot1.clone(); 11 } catch (CloneNotSupportedException e) { 12 // TODO Auto-generated catch block
13 e.printStackTrace(); 14 } 15 } 16
17 }
是的,因为此时的主调已经是子类的引用了。
上述代码在运行过程中会抛出"java.lang.CloneNotSupportedException",表明clone()方法并未正确执行完毕,问题的原因在与Java中的语法规定:
clone()的正确调用是需要实现Cloneable接口,如果没有实现Cloneable接口,并且子类直接调用Object类的clone()方法,则会抛出CloneNotSupportedException异常。
Cloneable接口仅是一个表示接口,接口本身不包含任何方法,用来指示Object.clone()可以合法的被子类引用所调用。
于是,上述代码改成如下形式,即可正确指定clone()方法以实现克隆。
1 package com.corn.objectsummary; 2
3 public class ObjectTest implements Cloneable { 4
5 public static void main(String[] args) { 6
7 ObjectTest ot1 = new ObjectTest(); 8
9 try { 10 ObjectTest ot2 = (ObjectTest) ot1.clone(); 11 System.out.println("ot2:" + ot2); 12 } catch (CloneNotSupportedException e) { 13 // TODO Auto-generated catch block
14 e.printStackTrace(); 15 } 16 } 17
18 }
三、克隆专讲。
1、
2、
3、