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

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

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




若将第 17 行标注(变成注释行),而撤消对第 18 行的标注,就会换用fillInStackTrace(),结果如下:  

  

originating the exception in f()  

Inside g(); e。printStackTrace()  

java。lang。Exception: thrown from f()  

        at Rethrowing。f(Rethrowing。java:8)  

        at Rethrowing。g(Rethrowing。java:12)  

        at Rethrowing。main(Rethrowing。java:24)  

Caught in main; e。printStackTrace()  

java。lang。Exception: thrown from f()  

        at Rethrowing。g(Rethrowing。java:18)  

        at Rethrowing。main(Rethrowing。java:24)  

  

由于使用的是fillInStackTrace() ,第18 行成为违例的新起点。  

针对 g()和 main(),Throwable 类必须在违例规格中出现,因为fillInStackTrace()会生成一个 Throwable 

对象的句柄。由于 Throwable 是 Exception 的一个基础类,所以有可能获得一个能够“掷”出的对象(具有 

Throwable 属性),但却并非一个 Exception (违例)。因此,在main()中用于Exception 的句柄可能丢失 

自己的目标。为保证所有东西均井然有序,编译器强制Throwable 使用一个违例规范。举个例子来说,下述 



                                                                                          268 


…………………………………………………………Page 270……………………………………………………………

程序的违例便不会在main()中被捕获到:  

  

//: ThrowOut。java  

public class ThrowOut {  

  public static void  

  main(String'' args) throws Throwable {  

    try {  

      throw new Throwable();   

    } catch(Exception e) {  

      System。out。println(〃Caught in main()〃);  

    }  

  }  

} ///:~  

  

也有可能从一个已经捕获的违例重新“掷”出一个不同的违例。但假如这样做,会得到与使用 

fillInStackTrace()类似的效果:与违例起源地有关的信息会全部丢失,我们留下的是与新的 throw 有关的 

信息。如下所示:  

  

//: RethrowNew。java  

// Rethrow a different object from the one that  

// was caught  

  

public class RethrowNew {  

  public static void f() throws Exception {  

    System。out。println(  

      〃originating the exception in f()〃);  

    throw new Exception(〃thrown from f()〃);  

  }  

  public static void main(String'' args) {  

    try {  

      f();  

    } catch(Exception e) {  

      System。out。println(  

        〃Caught in main; e。printStackTrace()〃);  

      e。printStackTrace();  

      throw new NullPointerException(〃from main〃);  

    }  

  }  

} ///:~  

  

输出如下:  

  

originating the exception in f()  

Caught in main; e。printStackTrace()  

java。lang。Exception: thrown from f()  

        at RethrowNew。f(RethrowNew。java:8)  

        at RethrowNew。main(RethrowNew。java:13)  

java。lang。NullPointerException: from main  

        at RethrowNew。main(RethrowNew。java:18)  

  

最后一个违例只知道自己来自main(),而非来自 f()。注意Throwable 在任何违例规范中都不是必需的。  



                                                                                          269 


…………………………………………………………Page 271……………………………………………………………

永远不必关心如何清除前一个违例,或者与之有关的其他任何违例。它们都属于用new 创建的、以内存堆为 

基础的对象,所以垃圾收集器会自动将其清除。  



9。3 标准 Java 违例  



Java 包含了一个名为Throwable 的类,它对可以作为违例“掷”出的所有东西进行了描述。Throwable 对象 

有两种常规类型(亦即“从Throwable 继承”)。其中,Error 代表编译期和系统错误,我们一般不必特意 

捕获它们(除在特殊情况以外)。Exception 是可以从任何标准 Java 库的类方法中“掷”出的基本类型。此 

外,它们亦可从我们自己的方法以及运行期偶发事件中“掷”出。  

为获得违例的一个综合概念,最好的方法是阅读由 http://java。sun。 提供的联机 Java 文档(当然,首先 

下载它们更好)。为了对各种违例有一个大概的印象,这个工作是相当有价值的。但大家不久就会发现,除 

名字外,一个违例和下一个违例之间并不存在任何特殊的地方。此外,Java 提供的违例数量正在日益增多; 

从本质上说,把它们印到一本书里是没有意义的。大家从其他地方获得的任何新库可能也提供了它们自己的 

违例。我们最需要掌握的是基本概念,以及用这些违例能够做什么。  

java。lang。Exception  

这是程序能捕获的基本违例。其他违例都是从它衍生出去的。这里要注意的是违例的名字代表发生的问题, 

而且违例名通常都是精心挑选的,可以很清楚地说明到底发生了什么事情。违例并不全是在 java。lang 中定 

义的;有些是为了提供对其他库的支持,如util,net 以及io等——我们可以从它们的完整类名中看出这一 

点,或者观察它们从什么继承。例如,所有IO违例都是从 java。io。IOException 继承的。  



9。3。1 RuntimeException 的特殊情况  



本章的第一个例子是:  

if(t == null)  

throw new NullPointerException();  

看起来似乎在传递进入一个方法的每个句柄中都必须检查 null (因为不知道调用者是否已传递了一个有效的 

句柄),这无疑是相当可怕的。但幸运的是,我们根本不必这样做——它属于 Java 进行的标准运行期检查的 

一部分。若对一个空句柄发出了调用,Java 会自动产生一个NullPointerException 违例。所以上述代码在 

任何情况下都是多余的。  

这个类别里含有一系列违例类型。它们全部由 Java 自动生成,毋需我们亲自动手把它们包含到自己的违例规 

范里。最方便的是,通过将它们置入单独一个名为 RuntimeException 的基础类下面,它们全部组合到一起。 

这是一个很好的继承例子:它建立了一系列具有某种共通性的类型,都具有某些共通的特征与行为。此外, 

我们没必要专门写一个违例规范,指出一个方法可能会“掷”出一个 RuntimeException,因为已经假定可能 

出现那种情况。由于它们用于指出编程中的错误,所以几乎永远不必专门捕获一个“运行期违例”—— 

RuntimeException——它在默认情况下会自动得到处理。若必须检查 RuntimeException,我们的代码就会变 

得相当繁复。在我们自己的包里,可选择“掷”出一部分 RuntimeException。  

如果不捕获这些违例,又会出现什么情况呢?由于编译器并不强制违例规范捕获它们,所以假如不捕获的 

话,一个RuntimeException 可能过滤掉我们到达 main()方法的所有途径。为体会此时发生的事情,请试试 

下面这个例子:  

  

//: NeverCaught。java  

// Ignoring RuntimeExceptions  

  

public class NeverCaught {  

  static void f() {  

    throw new RuntimeException(〃From f()〃);  

  }  

  static void g() {  

    f();  

  }  

  public static void main(String'' args) {  

    g();  

  }  



                                                                             270 


…………………………………………………………Page 272……………………………………………………………

} ///:~  

  

大家已经看到,一个RuntimeException (或者从它继承的任何东西)属于一种特殊情况,因为编译器不要求 

为这些类型指定违例规范。  

输出如下:  

  

java。lang。RuntimeException: From f()  

at NeverCaught。f(NeverCaught。java:9)  

at NeverCaught。g(NeverCaught。java:12)  

at NeverCaught。main(NeverCaught。java:15)  

  

所以答案就是:假若一个RuntimeException 获得到达main()的所有途径,同时不被捕获,那么当程序退出 

时,会为那个违例调用 printStackTrace()。  

注意也许能在自己的代码中仅忽略 RuntimeException,因为编译器已正确实行了其他所有控制。因为 

RuntimeException 在此时代表一个编程错误:  

(1) 一个我们不能捕获的错误(例如,由客户程序员接收传递给自己方法的一个空句柄)。  

(2) 作为一名程序员,一个应在自己的代码中检查的错误(如 ArrayIndexOutOfBoundException,此时应注 

意数组的大小)。  

可以看出,最好的做法是在这种情况下违例,因为它们有助于程序的调试。  

另外一个有趣的地方是,我们不可将Java 违例划分为单一用途的工具。的确,它们设计用于控制那些讨厌的 

运行期错误——由代码控制范围之外的其他力量产生。但是,它也特别有助于调试某些特殊类型的编程错 

误,那些是编译器侦测不到的。  



9。4 创建自己的违例  



并不一定非要使用Java 违例。这一点必须掌握,因为经常都需要创建自己的违例,以便指出自己的库可能生 

成的一个特殊错误——但创建 Java 分级结构的时候,这个错误是无法预知的。  

为创建自己的违例类,必须从一个现有的违例类型继承——最好在含义上与新违例近似。继承一个违例相当 

简单:  

  

//: Inheriting。java  

// Inheriting your own exceptions  

  

class MyException extends Exception {  

  public MyException() {}  

  public MyException(String msg) {  

    super(msg);  

  }  

}  

  

public class Inheriting {  

  public static vo id f() throws MyException {  

    System。out。println(  

      〃Throwing MyException from f()〃);  

    throw new MyException();  

  }  

  public static void g() throws MyException {  

    System。out。println(  

      〃Throwing MyException from g()〃);  

    throw new MyException(〃Originated in g()〃);  

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