友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
狗狗书籍 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

Java编程思想第4版[中文版](PDF格式)-第157章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




12。2。2 克隆对象  



若需修改一个对象,同时不想改变调用者的对象,就要制作该对象的一个本地副本。这也是本地副本最常见 

的一种用途。若决定制作一个本地副本,只需简单地使用 clone()方法即可。Clone 是“克隆”的意思,即制 

作完全一模一样的副本。这个方法在基础类Object 中定义成“protected”(受保护)模式。但在希望克隆 

的任何衍生类中,必须将其覆盖为“public”模式。例如,标准库类Vector 覆盖了 clone(),所以能为 

Vector 调用clone(),如下所示:  

  

//: Cloning。java  

// The clone() operation works for only a few  

// items in the standard Java library。  

import java。util。*;  

  

class Int {  

  private int i;  

  public Int(int ii) { i = ii; }  

  public void increment() { i++; }  

  public String toString() {   

    return Integer。toString(i);   

  }  

}  

  

public class Cloning {  

  public static void main(String'' args) {  

    Vector v = new Vector();  

    for(int i = 0; i 《 10; i++ )  

      v。addElement(new Int(i));  

    System。out。println(〃v: 〃 + v);  

    Vector v2 = (Vector)v。clone();  

    // Increment all v2's elements:  

    for(Enumeration e = v2。elements();  

        e。hasMoreElements(); )  

      ((Int)e。nextElement())。increment();  

    // See if it changed v's elements:  

    System。out。println(〃v: 〃 + v);  

  }  

} ///:~  

  

clone()方法产生了一个Object,后者必须立即重新造型为正确类型。这个例子指出Vector 的 clone()方法 

不能自动尝试克隆Vector 内包含的每个对象——由于别名问题,老的Vector 和克隆的Vector 都包含了相同 

的对象。我们通常把这种情况叫作“简单复制”或者“浅层复制”,因为它只复制了一个对象的“表面”部 

分。实际对象除包含这个“表面”以外,还包括句柄指向的所有对象,以及那些对象又指向的其他所有对 

象,由此类推。这便是“对象网”或“对象关系网”的由来。若能复制下所有这张网,便叫作“全面复制” 

或者“深层复制”。  

在输出中可看到浅层复制的结果,注意对 v2 采取的行动也会影响到 v:  

  

v: '0; 1; 2; 3; 4; 5; 6; 7; 8; 9'  

v: '1; 2; 3; 4; 5; 6; 7; 8; 9; 10'  

  

一般来说,由于不敢保证Vector 里包含的对象是“可以克隆”(注释②)的,所以最好不要试图克隆那些对 

象。  

  

②:“可以克隆”用英语讲是 cloneable,请留意Java 库中专门保留了这样的一个关键字。  



                                                                                             352 


…………………………………………………………Page 354……………………………………………………………

12。2。3 使类具有克隆能力  



尽管克隆方法是在所有类最基本的 Object 中定义的,但克隆仍然不会在每个类里自动进行。这似乎有些不可 

思议,因为基础类方法在衍生类里是肯定能用的。但Java 确实有点儿反其道而行之;如果想在一个类里使用 

克隆方法,唯一的办法就是专门添加一些代码,以便保证克隆的正常进行。  

  

1。 使用protected 时的技巧  

为避免我们创建的每个类都默认具有克隆能力,clone()方法在基础类Object 里得到了“保留”(设为 

protected)。这样造成的后果就是:对那些简单地使用一下这个类的客户程序员来说,他们不会默认地拥有 

这个方法;其次,我们不能利用指向基础类的一个句柄来调用 clone() (尽管那样做在某些情况下特别有 

用,比如用多形性的方式克隆一系列对象)。在编译期的时候,这实际是通知我们对象不可克隆的一种方 

式——而且最奇怪的是,Java 库中的大多数类都不能克隆。因此,假如我们执行下述代码:  

Integer x = new Integer(l);  

x = x。clone();  

那么在编译期,就有一条讨厌的错误消息弹出,告诉我们不可访问clone()——因为Integer并没有覆盖 

它,而且它对protected 版本来说是默认的)。  

但是,假若我们是在一个从Object 衍生出来的类中(所有类都是从 Object 衍生的),就有权调用 

Object。clone(),因为它是“protected ”,而且我们在一个继承器中。基础类clone()提供了一个有用的功 

能——它进行的是对衍生类对象的真正“按位”复制,所以相当于标准的克隆行动。然而,我们随后需要将 

自己的克隆操作设为public,否则无法访问。总之,克隆时要注意的两个关键问题是:几乎肯定要调用 

super。clone(),以及注意将克隆设为 public。  

有时还想在更深层的衍生类中覆盖 clone(),否则就直接使用我们的clone() (现在已成为public),而那 

并不一定是我们所希望的(然而,由于Object。clone()已制作了实际对象的一个副本,所以也有可能允许这 

种情况)。protected 的技巧在这里只能用一次:首次从一个不具备克隆能力的类继承,而且想使一个类变 

成“能够克隆”。而在从我们的类继承的任何场合,clone()方法都是可以使用的,因为Java 不可能在衍生 

之后反而缩小方法的访问范围。换言之,一旦对象变得可以克隆,从它衍生的任何东西都是能够克隆的,除 

非使用特殊的机制(后面讨论)令其“关闭”克隆能力。  

  

2。 实现Cloneable 接口  

为使一个对象的克隆能力功成圆满,还需要做另一件事情:实现Cloneable 接口。这个接口使人稍觉奇怪, 

因为它是空的!  

interface Cloneable {}  

之所以要实现这个空接口,显然不是因为我们准备上溯造型成一个Cloneable,以及调用它的某个方法。有 

些人认为在这里使用接口属于一种“欺骗”行为,因为它使用的特性打的是别的主意,而非原来的意思。 

Cloneable interface 的实现扮演了一个标记的角色,封装到类的类型中。  

两方面的原因促成了Cloneable interface 的存在。首先,可能有一个上溯造型句柄指向一个基础类型,而 

且不知道它是否真的能克隆那个对象。在这种情况下,可用 instanceof 关键字(第 11章有介绍)调查句柄 

是否确实同一个能克隆的对象连接:  

if(myHandle instanceof Cloneable) // 。。。  

第二个原因是考虑到我们可能不愿所有对象类型都能克隆。所以Object。clone()会验证一个类是否真的是实 

现了Cloneable 接口。若答案是否定的,则“掷”出一个 CloneNotSupportedException 违例。所以在一般情 

况下,我们必须将“implement Cloneable”作为对克隆能力提供支持的一部分。  



12。2。4  成功的克隆  



理解了实现 clone()方法背后的所有细节后,便可创建出能方便复制的类,以便提供了一个本地副本:  

  

//: LocalCopy。java  

// Creating local copies with clone()  

import java。util。*;  

  

class MyObject implements Cloneable {  

  int i;  



                                                                           353 


…………………………………………………………Page 355……………………………………………………………

  MyObject(int ii) { i = ii; }  

  public Object clone() {  

    Object o = null;  

    try {  

      o = super。clone();  

    } catch (CloneNotSupportedException e) {  

      System。out。println(〃MyObject can't clone〃);  

    }  

    return o;  

  }  

  public String toString() {  

    return Integer。toString(i);  

  }  

}  

  

public clas
返回目录 上一页 下一页 回到顶部 0 0
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!