有些代码必须捕获异常,捕获异常需要进行周密的计划。
如果某个异常发生的时候没有在任何地方进行捕获,那程序就会终止执行,并在控制台上打印出异常信息,其中包括异常的类型和堆栈的内容。对于图形界面程序(applet和application应用程序),在捕获异常之后,也会打印出堆栈的信息,但程序将返回到用户界面的处理循环中(在调试基于图形界面的程序时,最好保证控制台窗口可见,并且没有被极小化)。
捕获一个异常,必须设置try/catch语句块,如果在try语句块中的任何代码抛出了一个在catch+句中说明的异常类,那么:
1.程序将跳过try语句块的其余代码。
2.程序将执行catch子句中的处理器代码。
如果在try语句块中的代码没有抛出任何异常,那么程序将跳过catch子句。
如果方法中的任何代码抛出了一个在catch+句中没有声明的异常类型,那么这个方法就会立刻退出(期待调用者为这种类型的异常设计了catch子句)。
需要注意,try语句中的大多数代码都很容易理解:读取并处理文本行,直到遇到文件结束符为止。正如在JavaAPI中看到的那样,read方法有可能抛出一个IOException异常。在这种情况下,将跳出整个while循环,进入catch子句,并输出堆栈情况。对于一个普通的程序来说,这样处理异常基本上合乎情理。还有其他的选择吗?
通常,最好的选择是什么也不做,而是将异常传递给调用者。如果read方法出现了错误,就让read方法的调用者去操心!如果采用这种处理方式,就必须声明这个方法可能会抛出一个IOException。
请记住,编译器严格地执行throws说明符。如果调用了一个抛出已检查异常的方法,就必须对它进行处理,或者将它传递出去。
哪种方法更好呢?通常,应该捕获那些知道如何处理的异常,而将那些不知道怎样处理的异常传递出去。如果想将异常传递出去,就必须在方法的首部添加一个throws说明符以便告知调用者这个方法可能会抛出异常。
仔细阅读一下JavaAPI文档,以便知道每个方法可能会抛出哪种异常,然后再决定是自己处理,还是添加到throws列表。对于后一种情况,也不必犹豫。将异常直接交给能够胜任的处理器进行处理要比压制对它的处理更好。
同时请记住,这个规则也有一个例外。如果编写一个覆盖超类的方法,而这个方法又没有抛出异常,那么这个方法就必须捕获方法代码中出现的每一个已检查异常。不允许在子类的thrws说明符中出现超过超类方法所列出的异常类范围。