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

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

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




      new BackOn();  

      new ReallyNoMore();  

    };  

    Ordinary x = new Ordinary();  

    // This won't pile; since clone() is  

    // protected in Object:  

    //! x = (Ordinary)x。clone();  

    // tryToClone() checks first to see if  

    // a class implements Cloneable:  

    for(int i = 0; i 《 ord。length; i++)  

      tryToClone(ord'i');  

  }  

} ///:~  

  

第一个类Ordinary 代表着大家在本书各处最常见到的类:不支持克隆,但在它正式应用以后,却也不禁止对 

其克隆。但假如有一个指向Ordinary 对象的句柄,而且那个对象可能是从一个更深的衍生类上溯造型来的, 

便不能判断它到底能不能克隆。  

WrongClone 类揭示了实现克隆的一种不正确途径。它确实覆盖了 Object。clone(),并将那个方法设为 

public,但却没有实现Cloneable。所以一旦发出对super。clone()的调用(由于对Object。clone()的一个 

调用造成的),便会无情地掷出CloneNotSupportedException 违例。  

在 IsCloneable 中,大家看到的才是进行克隆的各种正确行动:先覆盖clone(),并实现了 Cloneable。但 

是,这个clone()方法以及本例的另外几个方法并不捕获CloneNotSupportedException 违例,而是任由它通 

过,并传递给调用者。随后,调用者必须用一个try…catch 代码块把它包围起来。在我们自己的clone()方 

法中,通常需要在 clone()内部捕获CloneNotSupportedException 违例,而不是任由它通过。正如大家以后 

会理解的那样,对这个例子来说,让它通过是最正确的做法。  

类NoMore 试图按照Java 设计者打算的那样“关闭”克隆:在衍生类clone()中,我们掷出 

CloneNotSupportedException 违例。TryMore 类中的clone()方法正确地调用 super。clone() ,并解析成 

NoMore。clone(),后者掷出一个违例并禁止克隆。  

但在已被覆盖的clone()方法中,假若程序员不遵守调用 super。clone()的“正确”方法,又会出现什么情况 

呢?在BackOn 中,大家可看到实际会发生什么。这个类用一个独立的方法duplicate()制作当前对象的一个 

副本,并在 clone()内部调用这个方法,而不是调用super。clone()。违例永远不会产生,而且新类是可以克 

隆的。因此,我们不能依赖“掷”出一个违例的方法来防止产生一个可克隆的类。唯一安全的方法在 

ReallyNoMore 中得到了演示,它设为 final,所以不可继承。这意味着假如clone()在 final 类中掷出了一 

个违例,便不能通过继承来进行修改,并可有效地禁止克隆(不能从一个拥有任意继承级数的类中明确调用 

Object。clone();只能调用 super。clone(),它只可访问直接基础类)。因此,只要制作一些涉及安全问题 

的对象,就最好把那些类设为final。  

在类CheckCloneable 中,我们看到的第一个类是tryToClone(),它能接纳任何Ordinary 对象,并用 

instanceof检查它是否能够克隆。若答案是肯定的,就将对象造型成为一个 IsCloneable,调用clone(), 

并将结果造型回Ordinary,最后捕获有可能产生的任何违例。请注意用运行期类型鉴定(见第 11章)打印 

出类名,使自己看到发生的一切情况。  

在main()中,我们创建了不同类型的Ordinary 对象,并在数组定义中上溯造型成为 Ordinary 。在这之后的 

头两行代码创建了一个纯粹的 Ordinary 对象,并试图对其克隆。然而,这些代码不会得到编译,因为 

clone()是 Object 中的一个protected (受到保护的)方法。代码剩余的部分将遍历数组,并试着克隆每个 

对象,分别报告它们的成功或失败。输出如下:  

  

Attempting IsCloneable  

Cloned IsCloneable  



                                                                                   365 


…………………………………………………………Page 367……………………………………………………………

Attempting NoMore  

Could not clone NoMore  

Attempting TryMore  

Could not clone TryMore  

Attempting BackOn  

Cloned BackOn  

Attempting ReallyNoMore  

Could not clone ReallyNoMore  

  

总之,如果希望一个类能够克隆,那么:  

(1) 实现Cloneable 接口  

(2) 覆盖 clone()  

(3) 在自己的clone()中调用super。clone()  

(4) 在自己的clone()中捕获违例  

这一系列步骤能达到最理想的效果。  



12。3。1 副本构建器  



克隆看起来要求进行非常复杂的设置,似乎还该有另一种替代方案。一个办法是制作特殊的构建器,令其负 

责复制一个对象。在C++中,这叫作“副本构建器”。刚开始的时候,这好象是一种非常显然的解决方案 

 (如果你是 C++程序员,这个方法就更显亲切)。下面是一个实际的例子:  

  

//: CopyConstructor。java  

// A constructor for copying an object  

// of the same type; as an attempt to create  

// a local copy。  

  

class FruitQualities {  

  private int weight;  

  private int color;  

  private int firmness;  

  private int ripeness;  

  private int smell;  

  // etc。  

  FruitQualities() { // Default constructor  

    // do something meaningful。。。  

  }  

  // Other constructors:  

  // 。。。  

  // Copy constructor:  

  FruitQualities(FruitQualities f) {  

    weight = f。weight;  

    color = f。color;  

    firmness = f。firmness;  

    ripeness = f。ripeness;  

    smell = f。smell;  

    // etc。  

  }  

}  

  

class Seed {  

  // Members。。。  

  Seed() { /* Default constructor */ }  



                                                                                             366 


…………………………………………………………Page 368……………………………………………………………

  Seed(Seed s) { /* Copy constructor */ }  

}  

  

class Fruit {  

  private FruitQualities fq;  

  private int seeds;  

  private Seed'' s;  

  Fruit(FruitQualities q; int seedCount) {   

    fq = q;  

    seeds = seedCount;  

    s = new Seed'seeds';  

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

      s'i' = new Seed();  

  }  

  // Other constructors:  

  // 。。。  

  // Copy constructor:  

  Fruit(Fruit f) {  

    fq = new FruitQualities(f。fq);  

    seeds = f。seeds;  

    // Call all Seed copy…constructors:  

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

      s'i' = new Seed(f。s'i');  

    // Other copy…construction activities。。。  

  }  

  // To allow derived constructors (or other   

  // methods) to put in different qualities:  

  protected void addQualities(FruitQualities q) {  

    fq = q;  

  }  

  protected FruitQualities getQualities() {  

    return fq;  

  }  

}  

  

class Tomato extends Fruit {  

  Tomato() {  

    super(new FruitQualities(); 100);  

  }  

  Tomato(Tomato t) { // Copy…constructor  

    super(t); // Upcast for base copy…constructor  

    // Other copy…construction activities。。。  

  }  

}  

  

class ZebraQualities extends FruitQualities {  

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