课程大纲
异常处理在所有语言中都有,是必须处理的一个功能,为增强程序的健壮性,计算机程序的编写也需要考虑处理这些异常情况,Java语言提供了异常处理功能,本章介绍Java异常处理机制。异常类继承层次
异常封装成为类Exception,此外,还有Throwable和Error类,异常类继承层次如图所示。
从图可见,所有的异常类都直接或间接地继承于java.lang.Throwable类。Throwable有两个直接子类:Error和Exception。
Error
Error是程序无法恢复的严重错误,程序员根本无能为力,只能让程序终止。例如:JVM内部错误、内存溢出和资源耗尽等严重情况。
Exception
Exception是程序可以恢复的异常,它是程序员所能掌控的。例如:除零异常、空指针访问、网络连接中断和读取不存在的文件等。本章所讨论的异常处理就是对Exception及其子类的异常处理。
Exception类可以分为:受检查异常和运行时异常。
受检查异常
如图19-1所示,受检查异常是除RuntimeException以外的异常类。它们的共同特点是:编译器会检查这类异常是否进行了处理,即要么捕获(try-catch语句),要么不抛出(通过在方法后声明throws),否则会发生编译错误。它们种类很多,前面遇到过的日期解析异常ParseException。
运行时异常
运行时异常是继承RuntimeException类的直接或间接子类。运行时异常往往是程序员所犯错误导致的,健壮的程序不应该发生运行时异常。它们的共同特点是:编译器不检查这类异常是否进行了处理,也就是对于这类异常不捕获也不抛出,程序也可以编译通过。由于没有进行异常处理,一旦运行时异常发生就会导致程序的终止,这是用户不希望看到的。由于19.2.1节除零示例的ArithmeticException异常属于RuntimeException异常,见图19-1所示,可以不用加try-catch语句捕获异常。
捕获异常
try-catch语句
try{ //可能会发生异常的语句} catch(Throwable e){ //处理异常e} catch(Throwable e){ //处理异常e} catch(Throwable e){ //处理异常e}
当捕获的多个异常类之间存在父子关系时,捕获异常顺序与catch代码块的顺序有关。一般先捕获子类,后捕获父类,否则子类捕获不到。
try-catch语句嵌套是可以任意嵌套。
有时在try-catch语句中会占用一些非Java资源,如:打开文件、网络连接、打开数据库连接和使用数据结果集等,这些资源并非Java资源,不能通过JVM的垃圾收集器回收,需要程序员释放。为了确保这些资源能够被释放可以使用finally代码块或Java7之后提供自动资源管理(Automatic Resource Management)技术。
try-catch语句后面还可以跟有一个finally代码块:
try{ //可能会生成异常语句} catch(Throwable e1){ //处理异常e1} catch(Throwable e2){ //处理异常e2} catch(Throwable eN){ //处理异常eN} finally{ //释放资源}
在Java 7之后提供自动资源管理(Automatic Resource Management)技术,可以替代finally代码块,优化代码结构,提高程序可读性。
try (声明或初始化资源语句) { //可能会生成异常语句} catch(Throwable e1){ //处理异常e1} catch(Throwable e2){ //处理异常e1} catch(Throwable eN){ //处理异常eN}
在try语句后面添加一对小括号“()”,其中是声明或初始化资源语句,可以有多条语句语句之间用分号“;”分隔。
抛出异常
在一个方法中如果能够处理异常,则需要捕获并处理。但是本方法没有能力处理该异常,捕获它没有任何意义,则需要在方法后面声明抛出该异常,通知上层调用者该方法有可以发生异常。
方法后面声明抛出使用throws关键字,多个异常之间采用逗号(,)分隔。格式如下:
class className { [public | protected | private ] [static] [final | abstract] [native] [synchronized] type methodName([paramList]) [throws exceptionList] { //方法体 }}
Java异常相关的关键字中有两个非常相似,它们是throws和throw,throws用于方法后声明抛出异常,而throw关键字用来人工引发异常。
throw Throwable或其子类的实例
所有Throwable或其子类的实例都可以通过throw语句抛出。