远见与创新

2006-08-12

Think in Java 第九章 - Exception 笔记

Throwable类

Throwable类对可以作为违例"掷"出的所有东西进行了描述。Throwable对象有两种继承类。Error类代表编译期和系统错误,一般不必特意捕获它们,而Exception类需要捕获,它可以从任何标准Java库的类方法中"掷"出的基本类型,亦可从我们自己的方法以及运行期偶发事件中"掷"出。

Throwable类必须在违例规格中出现,因为fillInStackTrace()会生成一个Throwable对象的句柄。

Exception类

Exception类是所有违例类的基础类,它不提供关于违例太多的信息。它的基础类Throwable提供更多方法以提供更多信息:

String getMessage() : 获得详细的消息。
String toString() : 返回对Throwable的一段简要说明,其中包括详细的消息(如果有的话)。
void printStackTrace(),void printStackTrace(PrintStream) : 打印出Throwable和Throwable的调用堆栈路径。调用堆栈显示出将我们带到违例发生地点的方法调用的顺序。

除此以外,我们还可从Throwable的基础类Object类获得另外一些方法。对于违例控制来说,其中一个可能有用的是getClass(),它的作用是返回一个对象,用它代表这个对象的类。可依次用getName()或toString()查询这个Class类的名字。

捕获

catch(Exception e)

重新"掷"出

throw e; throw e.fillInStackTrace();

重新"掷"出一个违例从而进入更高一级的违例控制器中。

若只是简单地重新掷出当前违例,那么在更高一级的违例控制器中,用printStackTrace()打印出来的信息会与违例的起源地对应,而不是与重新掷出它的地点对应。调用fillInStackTrace()使当前堆栈的信息填充到原来的违例对象里然后掷出。

可以从一个已经捕获的违例"掷"出一个不同的违例。这样做会得到与使用fillInStackTrace()类似的效果:与违例起源地有关的信息会全部丢失,留下的是与新的throw有关的信息。

RuntimeException

RuntimeException属于Java进行的标准运行期检查的一部分。没必要专门写一个违例规范指出它可能会被"掷"出。而由于它们是用于指出编程中的错误的,在默认情况下会自动得到处理,所以也几乎永远不必专门来捕获它。

假若一个RuntimeException发生而没有被捕获直到main(),那么当程序退出时,Java会为那个违例自动调用printStackTrace(),报错。

创建自己的违例

由于默认构建器将一定被自动调用,所以衍生类的构建器必须在自己的违例规范中声明所有的基础类构建器违例,这就是说要强迫衍生类方法遵守基础类方法的违例规范。通过这种强迫,对象的替换可保持连贯性。(OK to add new exceptions for constructors, but you must deal with the base constructor exceptions )

一个方法的衍生类版本可以不产生任何违例--即便基础类版本要产生违例。

假如我们明确操作一个对象,编译器就会强迫我们只捕获特定于那个类的违例。但假如我们上溯造型到基础类型,编译器就会强迫我们捕获针对基础类的违例。通过所有这些限制,违例控制代码的"健壮"程度获得了大幅度改善。

非构造器方法的"违例规范接口"可能在继承和覆盖时变得更"窄",但它不会变得更"宽"--这与继承时的类接口规则是正好相反的。(Interface CANNOT add exceptions to existing methods from the base class)

finally块

无论是否在try块中发生违例,finally都会被执行,都会在违例控制机制转到更高级别之前执行。即使调用了break和continue语句,finally语句也会执行。值得注意的是,与作上标签的break和continue一道,finally排除了Java对goto跳转语句的需求。

特别留意构建器中的违例

构建器将对象置于一个安全的起始状态,但它可能执行一些操作--如打开一个文件。除非用户完成对象的使用,并调用一个特殊的清除方法,否则那些操作不会得到正确的清除。若从一个构建器内部"掷"出一个违例,这些清除行为也可能不会正确地发生。所有这些都意味着在编写构建器时,我们必须特别加以留意。

违例和控制器的匹配

在违例和它的控制器之间,并不需要非常精确的匹配。一个衍生类对象可与基础类的一个控制器相配。这一点非常重要,因为一旦决定为一个方法添加更多的违例,而且它们都是从相同的基础类继承的,那么客户程序员的代码就不需要更改。至少能够假定它们捕获的是基础类。

Technorati :

标签:

0 Comments:

发表评论

<< Home