8.2 捕获异常
扫码看视频
当Java运行时系统接收到异常对象时,会寻找能处理这一异常的代码,并把当前异常对象交给其处理,这一过程称为捕获(catch)异常。如果Java运行时系统找不到可以捕获异常的代码,则运行时系统将终止,相应的Java程序也将退出。最终Java运行时系统将异常的相关信息输出到System.err中,就如图8-1所示的那样。
那么如何捕获异常呢?在Java中,捕获异常需要使用catch关键字,而后紧跟catch关键字的语句块就是错误处理代码。捕获异常犹如狩猎,无法发现猎物就谈不上捕猎,所以在catch语句块的前面需要一个try语句块来监视异常的抛出。try语句块就是try关键字跟随的语句块,其中是可能引发异常的代码。如下所示:
这就是Java中异常处理的模式:先监视(try)后捕获(catch)。至于异常本身,它也是一个对象,有它自己的类型,所以我们的catch需要指定一个异常的类型。当程序在运行期间出现一个错误时,Java运行时系统会在对象堆中创建一个异常类型的对象,并在指定的catch语句块中赋给匹配的异常类型的变量(上例中的e1和e2)。
下面修改代码8.1,添加异常捕获代码,如代码8.2所示。
程序运行的结果为:
终于不用看到“奇怪”的异常信息了。这就是异常捕获的好处,可以给用户更友好的提示信息,并且程序在捕获了异常后,还可以继续运行。
提示:在java.lang.System类中有三个静态对象:out、err和in,分别代表标准输出流、标准错误输出流和标准输入流,out对象和err对象的类型都是java.io.PrintStream,因此它们的方法都是一样的。
所有异常类的基类都是Throwable,在这个类中有三个常用的方法,用于输出异常的相关信息,如下所示:
● public String getMessage()
返回异常对象的详细信息。
● public String toString()
返回异常对象的简短描述。
● public void printStackTrace()
将异常对象的栈跟踪信息打印到标准的错误流(System.err对象)中。
下面修改代码8.2,使用上述三个方法,输出异常的相关信息,如代码8.3所示。
注意,printStackTrace方法本身就是输出异常的栈跟踪信息,因此不需要、也不能调用System.err.println。
程序运行的结果为:
从输出结果可以看到:(1)toString方法所谓的异常对象简短描述,其信息比getMessage方法要更详细;(2)printStackTrace方法输出的信息很全面,包含了异常发生时的栈跟踪信息,这与没有进行异常捕获时,Java运行时系统输出的信息是一样的。
在实际开发时,可以根据需要选择这三个方法中的一个来获取或输出异常信息,当然也可以像代码8.2那样,给出错误提示信息。
一段代码可能会引发多种异常,因此捕获异常的catch语句可以有多个,我们看代码8.4。
编译ExcepTest.java,编译器提示错误如图8-3所示。
图8-3 因catch异常类型顺序错误而引发错误
引起这个错误的原因是:Exception类是所有异常类的基类,因此不管抛出何种异常,catch(Exception e)都能进行捕获,异常捕获机制是,只要发现了有匹配的,就不会再执行后面的catch语句,因此catch(ArithmeticException ae)就成了摆设,编译器发现了这个问题,就报告错误了。
因此,在使用多个catch语句捕获异常时,要将特殊的、具体的异常类型(派生类)放前面,一般化的异常类型(基类)放后面。修改代码8.4,如代码8.5所示。
再次编译运行,一切正常。