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

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

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




}  

  

class Amphibian extends Animal {  

  Characteristic p =   

    new Characteristic(〃can live in water〃);  

  Amphibian() {  

    System。out。println(〃Amphibian()〃);  

  }  

  protected void finalize() {  



                                                                                             200 


…………………………………………………………Page 202……………………………………………………………

    System。out。println(〃Amphibian finalize〃);  

    if(DoBaseFinalization。flag)  

      try {  

        super。finalize();  

      } catch(Throwable t) {}  

  }  

}  

  

public class Frog extends Amphibian {  

  Frog() {  

    System。out。println(〃Frog()〃);  

  }  

  protected void finalize() {  

    System。out。println(〃Frog finalize〃);  

    if(DoBaseFinalization。flag)  

      try {  

        super。finalize();  

      } catch(Throwable t) {}  

  }  

  public static void main(String'' args) {  

    if(args。length != 0 &&   

       args'0'。equals(〃finalize〃))  

       DoBaseFinalization。flag = true;  

    else  

      System。out。println(〃not finalizing bases〃);  

    new Frog(); // Instantly bees garbage  

    System。out。println(〃bye!〃);  

    // Must do this to guarantee that all   

    // finalizers will be called:  

    System。runFinalizersOnExit(true);  

  }  

} ///:~  

  

DoBasefinalization 类只是简单地容纳了一个标志,向分级结构中的每个类指出是否应调用 

super。finalize()。这个标志的设置建立在命令行参数的基础上,所以能够在进行和不进行基础类收尾工作 

的前提下查看行为。  

分级结构中的每个类也包含了 Characteristic 类的一个成员对象。大家可以看到,无论是否调用了基础类收 

尾模块,Characteristic 成员对象都肯定会得到收尾(清除)处理。  

每个被覆盖的finalize()至少要拥有对 protected 成员的访问权力,因为 Object 类中的finalize()方法具 

有protected 属性,而编译器不允许我们在继承过程中消除访问权限(“友好的”比“受到保护的”具有更 

小的访问权限)。  

在Frog。main()中,DoBaseFinalization 标志会得到配置,而且会创建单独一个Frog 对象。请记住垃圾收集 

 (特别是收尾工作)可能不会针对任何特定的对象发生,所以为了强制采取这一行动, 

System。runFinalizersOnExit(true)添加了额外的开销,以保证收尾工作的正常进行。若没有基础类初始 

化,则输出结果是:  

  

not finalizing bases  

Creating Characteristic is alive  

LivingCreature()  

Creating Characteristic has heart  

Animal()  

Creating Characteristic can live in water  



                                                                                             201 


…………………………………………………………Page 203……………………………………………………………

Amphibian()  

Frog()  

bye!  

Frog finalize  

finalizing Characteristic is alive  

finalizing Characteristic has heart  

finalizing Characteristic can live in water  

  

从中可以看出确实没有为基础类Frog 调用收尾模块。但假如在命令行加入“finalize”自变量,则会获得下 

述结果:  

  

Creating Characteristic is alive  

LivingCreature()  

Creating Characteristic has heart  

Animal()  

Creating Characteristic can live in water  

Amphibian()  

Frog()  

bye!  

Frog finalize  

Amphibian finalize  

Animal finalize  

LivingCreature finalize  

finalizing Characteristic is alive  

finalizing Characteristic has heart  

finalizing Characteristic can live in water  

  

尽管成员对象按照与它们创建时相同的顺序进行收尾,但从技术角度说,并没有指定对象收尾的顺序。但对 

于基础类,我们可对收尾的顺序进行控制。采用的最佳顺序正是在这里采用的顺序,它与初始化顺序正好相 

反。按照与 C++中用于“破坏器”相同的形式,我们应该首先执行衍生类的收尾,再是基础类的收尾。这是 

由于衍生类的收尾可能调用基础类中相同的方法,要求基础类组件仍然处于活动状态。因此,必须提前将它 

们清除(破坏)。  



7。7。3  构建器内部的多形性方法的行为  



构建器调用的分级结构(顺序)为我们带来了一个有趣的问题,或者说让我们进入了一种进退两难的局面。 

若当前位于一个构建器的内部,同时调用准备构建的那个对象的一个动态绑定方法,那么会出现什么情况 

呢?在原始的方法内部,我们完全可以想象会发生什么——动态绑定的调用会在运行期间进行解析,因为对 

象不知道它到底从属于方法所在的那个类,还是从属于从它衍生出来的某些类。为保持一致性,大家也许会 

认为这应该在构建器内部发生。  

但实际情况并非完全如此。若调用构建器内部一个动态绑定的方法,会使用那个方法被覆盖的定义。然而, 

产生的效果可能并不如我们所愿,而且可能造成一些难于发现的程序错误。  

从概念上讲,构建器的职责是让对象实际进入存在状态。在任何构建器内部,整个对象可能只是得到部分组 

织——我们只知道基础类对象已得到初始化,但却不知道哪些类已经继承。然而,一个动态绑定的方法调用 

却会在分级结构里“向前”或者“向外”前进。它调用位于衍生类里的一个方法。如果在构建器内部做这件 

事情,那么对于调用的方法,它要操纵的成员可能尚未得到正确的初始化——这显然不是我们所希望的。  

通过观察下面这个例子,这个问题便会昭然若揭:  

  

//: PolyConstructors。java  

// Constructors and polymorphism  

// don't produce what you might expect。  

  

abstract class Glyph {  



                                                                                     202 


…………………………………………………………Page 204……………………………………………………………

  abstract void draw();  

  Glyph()  {  

    System。out。println(〃Glyph() before draw()〃);  

    draw();   

    System。out。println(〃Glyph() after draw()〃);  

  }  

}  

  

class RoundGlyph extends Glyph {  

  int radius = 1;  

  RoundGlyph(int r) {  

    radius = r;  

    System。out。println(  

      〃RoundGlyph。RoundGlyph(); radius = 〃  

      + radius);  

  }  

  void draw() {   

    System。out。println(  

      〃RoundGlyph。draw(); radius = 〃 + radius);  

  }  

}  

  

public class PolyConstructors {  

  public static void main(String'' args) {  

    new RoundGlyph(5);  

  }  

} ///:~  

  

在Glyph 中,draw()方法是“抽象的”(abstract ),所以它可以被其他方法覆盖。事实上,我们在 

RoundGlyph 中不得不对其进行覆盖。但Glyph 构建器会调用这个方法,而且调用会在RoundGlyph。draw()中 

止,这看起来似乎是有意的。但请看看输出结果:  

  

Glyph() before draw()  

RoundGlyph。draw(); radius = 0  

Glyph() after draw()  

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