编程开发

java克隆详述-下

04-09-01 | No Comments |

  何为影子clone?先看一个例子。

  1. //倒霉的羊 
  2. public class Sheep implements Cloneable { 
  3.     private String name; 
  4.  
  5.     public void setName(String arg) { 
  6.         name = arg; 
  7.     } 
  8.  
  9.     public String getName() { 
  10.         return name; 
  11.     } 
  12.  
  13.     public Object clone() throws CloneNotSupportedException { 
  14.         return super.clone(); 
  15.     } 
  16.  
  17. // 羊圈 
  18. public class Sheepfold implements Cloneable { 
  19.     public Sheep sheep; 
  20.  
  21.     public String name; 
  22.  
  23.     public Sheepfold() { 
  24.         sheep = new Sheep(); 
  25.     } 
  26.  
  27.     public Object clone() throws CloneNotSupportedException { 
  28.         return super.clone(); 
  29.     } 
  30.  
  31. // 克隆 
  32. public class Main { 
  33.     public static void main(String[] args) throws Exception { 
  34.         Sheepfold fold = new Sheepfold(); 
  35.         fold.name = "小羊圈"
  36.         fold.sheep.setName("小羊"); 
  37.         Sheepfold fold2 = (Sheepfold) fold.clone(); 
  38.         System.out.println(" fold2.name = " + fold2.name); 
  39.         System.out.println(" fold2.sheep.getName() = " + fold2.sheep.getName()); 
  40.         fold2.name = "大羊圈"
  41.         fold2.sheep.setName("大羊"); 
  42.         System.out.println("====================================="); 
  43.         System.out.println(" fold2.name = " + fold2.name); 
  44.         System.out 
  45.                 .println("* fold2.sheep.getName() = " + fold2.sheep.getName()); 
  46.         System.out.println(" fold.name = " + fold.name); 
  47.         System.out.println("* fold.sheep.getName() = " + fold.sheep.getName()); 
  48.         System.out.println("====================================="); 
  49.     } 

  在这个例子中有三个类,Sheep和Sheepflod都实现了Cloneable接口,并且覆写了Object类的clone方法,说明这两个类是具有克隆能力的。注意一点,在Sheepflod中持有一个Sheep的实例,并在Main类中对其进行克隆,结果如下:
fold2.name = 小羊圈
fold2.sheep.getName() = 小羊
=====================================
fold2.name = 大羊圈
* fold2.sheep.getName() = 大羊
fold.name = 小羊圈
* fold.sheep.getName() = 大羊
=====================================

请注意一下结果中带有"*"号的两条结果语句。fold2.sheep和fold.sheep的name都变为了"大羊",很奇怪是吗?在此之前,我们只对fold2.sheep的name赋过值。为什么fold.sheep的name也变为了"大羊"呢?原因很简单,因为它们是指向同一个对象的不同引用。从中可以看出,调用Object类中clone()方法时,首先在内存中划分一块同原对象相同的空间,然后将原对象的内容原样拷贝至新对象。我们知道,java中有基本数据类型,对于基本数据类型,这样的操作是没有问题的,但对非基本类型变量,它们保存的仅仅是对象的引用,这也是为什么clone后非基本类型变量和原对象中的变量指向同一个对象的原因。可能你已经注意到,程序中用到了String类型,即对象,为什么没有出现引用指向同一地址的情况?这是因为String是一个不可更改的类(immutable class),每次给它赋值时,都会产生一个新的String对象。如String str = "a"; str += "b";在这两句代码中,当执行str += "b"时,实际上是重新成生了一个值为"ab"的String对象,即重新分配了一块内存空间。以上clone方法通常被称为"影子clone"。"影子 clone"给我们留下了一个问题,即多个引用指向同一个对象。如何解决该问题呢?答案为"深度clone"。把上面的例子改成深度clone很简单,只需将Sheepfold的clone()方法改为如下即可:

  1. public Object clone() throws CloneNotSupportedException { 
  2.     Sheepfold fold = (Sheepfold) super.clone(); 
  3.     sheep = (Sheep) fold.sheep.clone(); 
  4.     return fold; 
  5. }

  至此,clone就基本完成了。当然,在实际使用过程中需要注意一些问题,比如StringBuffer不可以直接clone(当然,也有解决办法)等等。

完!


五冠 Nokia/诺基亚 5230 5230XM 送证书V20版 内有港行 销数千台
1000.0元
批发 雷朋3025镜面反光太阳镜 太阳眼镜 19.9/副 顶级质量
19.9元
促销笔记本电脑 13.3英寸超薄N450无线网卡视频
1999.0元

留下您的脚印


«
»