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

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

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





…………………………………………………………Page 276……………………………………………………………

  // but you must deal with the base constructor  

  // exceptions:  

  StormyInning() throws RainedOut;   

    BaseballException {}  

  StormyInning(String s) throws Foul;   

    BaseballException {}  

  // Regular methods must conform to base class:  

//! void walk() throws PopFoul {} //pile error  

  // Interface CANNOT add exceptions to existing  

  // methods from the base class:  

//! public void event() throws RainedOut {}  

  // If the method doesn't already exist in the  

  // base class; the exception is OK:  

  public void rainHard() throws RainedOut {}  

  // You can choose to not throw any exceptions;  

  // even if base version does:  

  public void event() {}  

  // Overridden methods can throw   

  // inherited exceptions:  

  void atBat() throws PopFoul {}  

  public static void main(String'' args) {  

    try {  

      StormyInning si = new StormyInning();  

      si。atBat();  

    } catch(PopFoul e) {  

    } catch(RainedOut e) {  

    } catch(BaseballException e) {}  

    // Strike not thrown in derived version。  

    try {  

      // What happens if you upcast?  

      Inning i = new StormyInning();  

      i。atBat();  

      // You must catch the exceptions from the  

      // base…class version of the method:  

    } catch(Strike e) {  

    } catch(Foul e) {  

    } catch(RainedOut e) {  

    } catch(BaseballException e) {}  

  }  

} ///:~  

  

在 Inning 中,可以看到无论构建器还是event()方法都指出自己会“掷”出一个违例,但它们实际上没有那 

样做。这是合法的,因为它允许我们强迫用户捕获可能在覆盖过的event()版本里添加的任何违例。同样的 

道理也适用于abstract 方法,就象在 atBat()里展示的那样。  

 “interface Storm”非常有趣,因为它包含了在 Ining 中定义的一个方法——event(),以及不是在其中 

定义的一个方法。这两个方法都会“掷”出一个新的违例类型:RainedOut。当执行到“StormyInning  

extends”和“implements Storm”的时候,可以看到Storm 中的event()方法不能改变 Inning中的event() 

的违例接口。同样地,这种设计是十分合理的;否则的话,当我们操作基础类时,便根本无法知道自己捕获 

的是否正确的东西。当然,假如interface 中定义的一个方法不在基础类里,比如rainHard(),它产生违例 

时就没什么问题。  

对违例的限制并不适用于构建器。在StormyInning 中,我们可看到一个构建器能够“掷”出它希望的任何东 

西,无论基础类构建器“掷”出什么。然而,由于必须坚持按某种方式调用基础类构建器(在这里,会自动 



                                                                                          275 


…………………………………………………………Page 277……………………………………………………………

调用默认构建器),所以衍生类构建器必须在自己的违例规范中声明所有基础类构建器违例。  

StormyInning。walk()不会编译的原因是它“掷”出了一个违例,而 Inning。walk()却不会“掷”出。若允许 

这种情况发生,就可让自己的代码调用 Inning。walk(),而且它不必控制任何违例。但在以后替换从 Inning 

衍生的一个类的对象时,违例就会“掷”出,造成代码执行的中断。通过强迫衍生类方法遵守基础类方法的 

违例规范,对象的替换可保持连贯性。  

覆盖过的event()方法向我们显示出一个方法的衍生类版本可以不产生任何违例——即便基础类版本要产生 

违例。同样地,这样做是必要的,因为它不会中断那些已假定基础类版本会产生违例的代码。差不多的道理 

亦适用于atBat(),它会“掷”出PopFoul——从 Foul 衍生出来的一个违例,而Foul 违例是由 atBat()的基 

础类版本产生的。这样一来,假如有人在自己的代码里操作 Inning,同时调用了atBat(),就必须捕获Foul 

违例。由于 PopFoul 是从Foul 衍生的,所以违例控制器(模块)也会捕获PopFoul。  

最后一个有趣的地方在 main()内部。在这个地方,假如我们明确操作一个StormyInning 对象,编译器就会 

强迫我们只捕获特定于那个类的违例。但假如我们上溯造型到基础类型,编译器就会强迫我们捕获针对基础 

类的违例。通过所有这些限制,违例控制代码的“健壮”程度获得了大幅度改善(注释③)。  

  

③:ANSI/ISO C++施加了类似的限制,要求衍生方法违例与基础类方法掷出的违例相同,或者从后者衍生。 

在这种情况下,C++实际上能够在编译期间检查违例规范。  

  

我们必须认识到这一点:尽管违例规范是由编译器在继承期间强行遵守的,但违例规范并不属于方法类型的 

一部分,后者仅包括了方法名以及自变量类型。因此,我们不可在违例规范的基础上覆盖方法。除此以外, 

尽管违例规范存在于一个方法的基础类版本中,但并不表示它必须在方法的衍生类版本中存在。这与方法的 

 “继承”颇有不同(进行继承时,基础类中的方法也必须在衍生类中存在)。换言之,用于一个特定方法的 

 “违例规范接口”可能在继承和覆盖时变得更“窄”,但它不会变得更“宽”——这与继承时的类接口规则 

是正好相反的。  



9。6 用 finally 清除  



无论一个违例是否在try 块中发生,我们经常都想执行一些特定的代码。对一些特定的操作,经常都会遇到 

这种情况,但在恢复内存时一般都不需要(因为垃圾收集器会自动照料一切)。为达到这个目的,可在所有 

违例控制器的末尾使用一个finally 从句(注释④)。所以完整的违例控制小节象下面这个样子:  

  

try {  

// 要保卫的区域:  

// 可能“掷”出A;B;或C 的危险情况  

} catch (A a1) {  

// 控制器 A  

} catch (B b1) {  

// 控制器 B  

} catch (C c1) {  

// 控制器 C  

} finally {  

// 每次都会发生的情况  

}  

  

④:C++违例控制未提供finally 从句,因为它依赖构建器来达到这种清除效果。  

  

为演示 finally 从句,请试验下面这个程序:  

  

//: FinallyWorks。java  

// The finally clause is always executed  

  

public class FinallyWorks {  

  static int count = 0;  

  public static void main(String'' args) {  



                                                                              276 


…………………………………………………………Page 278……………………………………………………………

    while(true) {  

      try {  

        // post…increment is zero first time:  

        if(count++ == 0)  

          throw new Exception();  

        System。out。println(〃No exception〃);  

      } catch(Exception e) {  

        System。out。println(〃Exception thrown〃);  

      } finally {  

        System。out。println(〃in finally clause〃);  

        if(count == 2) break; // out of 〃while〃  

      }  

    }  

  }  

} ///:~  

  

通过该程序,我们亦可知道如何应付Java 违例(类似 C++的违例)不允许我们恢复至违例产生地方的这一事 

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