Java异常处理总结
异常(Exception):指程序运行过程中出现的非正常现象。
1、 Java异常的异常处理机制
早期的情况:
早期使用的程序设计语言是没有提供专门进行异常处理功能的,程序设计人员只能苦逼的使用条件语句对各种可能设想到的错误情况进行判断,来捕捉特定的异常,然后进行相应的处理。这样的处理方式,往往要整出大段大段的if…else语句。本来需要完成相应功能的代码块很小,但是加上这样针对异常处理的条件语句使得代码显得非常臃肿,这样一来代码的可读性和可维护性就下降了,而且有时候还会遗漏意想不到的异常情况。
Java的出现:
针对上面的情况Java提供了强大的异常处理机制,可以说为程序猿带来了福音,Java的异常处理机制可以很方便的在程序中监视可能发生异常的程序块,并将所有的异常处理代码集中放在程序的某处,使完成正常功能的程序代码与进行异常处理的程序代码分开。通过异常处理机制,减少了编程人员的工作量,增强了异常处理的灵活性,并使得程序的可读性和可维护性大大的提高了。
在Java的处理机制中,引入了一些用来描述和处理异常的类,每个异常类反映一类运行的错误,在类的定义中包含了该类异常的信息和对异常进行处理的方法。对程序运行的过程中发生某一个异常现象时,系统就产生了一个与之相应的异常类对象,并交由系统中的相应机制进行处理,以避免系统崩溃或其他对系统有害的结果发生,保证了程序运行的安全性。
2、 Java异常类的定义
Java中,把异常分为:错误(Error)和异常情况(Exception)。
错误(Error):指程序本身存在非法的情形,这些情形常常是因为代码存在着问题而引起的。而且编程人员可以通过对程序进行更新仔细的检查,把这种错误的情形减小到最小,从理论上讲,这些情形是可以避免的。
异常情况(Exception):表示另外一种“非同寻常”的错误。这种错误通常是不可预测的。常见的异常情况包括内存不足,找不到所需要的文件等。
Throwable类派生了两个子类:Exception和Error。
Error类描述内部的错误,它由系统保留,程序不能抛出这个类型的对象,Error类的对象不可捕获,不可以恢复,出错时系统通知用户并终止程序;
Exception类则供应程序的使用,所有的Java异常类都是系统类库中的Exception类的子类。
继承关系:
3、 系统定义的运行异常
Exception类有若干个子类,每个子类代表了一种特定的运行错误。有些子类是系统事先定义并包含在Java类库中的,称为系统定义的运行异常。
系统定义的运行异常 |
说明 |
ClassNotFoundException |
找不到要装载的类,由Class.forName抛出 |
ArrayIndexOutOfBoundsException |
数组下标出界 |
FileNotFoundException |
找不到指定的文件或目录 |
IOException |
输入/输出错误 |
NullPointerException |
非法使用空引用 |
ArithmeticException |
算术错误,如除数为0 |
InterruptedException |
一个线程被另一个线程中断 |
UnknownHostException |
无法确定主机的IP地址 |
SecurityException |
安全性错误 |
MaliformedURLException |
URL格式错误 |
4、 用户自定义的异常
系统定义的异常主要用来处理系统可以预见的较常见的运行错误,如果预计程序可能产生一个特定的异常问题,该问题无法用系统定义的异常情况来描述,此时就需要程序人员根据特殊逻辑,在用户程序里自定义一个异常情况和异常对象。这种用户自定义的异常类和异常对象的主要用来处理用户程序中特定的逻辑运行错误。
用户自定义的异常时,一般需要完成如下工作。
(1) 生命一个新的异常类,作为Exception类或其他某一个已经存在的系统异常类或其他异常类的子类。
(2) 为新的异常类定义属性和方法,或重载父类的属性和方法,使这些属性和方法能够体现该类所对应的错误信息。
(3) 只有定义了异常类,系统才能够识别特定的运行错误,才能够及时的控制和处理这些运行错误,所以定义足够的多的异常类是构建一个稳定完善的应用系统的重要基础之一。
5、 异常的抛出
Java应用程序在运行时如果出现了一个可识别的错误,就会产生一个与该错误相对的异常类的对象,这个过程称为异常的抛出。
被抛出的异常对象包含了异常的类型和错误出现时程序所处的状态信息,这个异常对象就会交给java虚拟机,由虚拟机来寻找具体的异常处理者。
根据异常类的不同,抛出异常方法也不同,可分为系统自动抛出的异常和语句抛出的异常两种情况。
(1) 系统自动抛出的异常:所有系统定义的运行异常都可以由系统自动抛出。
(2) 语句抛出的异常:用户自定义的异常不可能依靠系统自动抛出,而必须通过throw语句定义异常错误,并抛出这个异常类的对象。使用时,在方法声明中用throws子句声明抛出的异常,在方法体重通过throw语句实现抛出异常对象。
注:使用throw语句抛出异常时应该注意如下两个问题:
(1) 一般这种抛出异常的语句应该定义为满足一定条件时执行,例如把throw语句放在if语句的if分支中,只有当条件得到满足,即用户定义的逻辑错误发生时才执行。
(2) 含有throw语句的方法应该在方法定义中增加如下部分:throws异常类名列表
这样做的目的就是为了通知所有想调用此方法的方法。由于该方法包含throw语句,所以要准备接受和处理它在运行的过程中可能会抛出的异常。如果方法中的throw语句不止一个,方法头的异常类名列表也不止一个,应该包含所有可能产生的异常。
6、 异常的处理
从上面知道,抛出异常很简单的,那么怎么来处理这个被抛出的异常呢??
异常的处理主要包括:捕捉异常、程序流程的跳转和异常处理的语句块的定义等。当一个异常被抛出的时候,应该有专门的语句来捕捉这个被抛出的异常对象,这个过程被称为捕捉异常,当一个异常类的对象被捕捉可接收以后,用户的程序就会发生流程的跳转,系统终止当前的流程而跳转至专门的异常处理语句块,或者直接跳出当前的程序和java虚拟机回到操作系统。
异常的处理有两种方法:
(1) 是使用try…catch…finally结构对异常进行捕获和处理。
(2) 通过throws和throw抛出异常。
说明:
(1) 将可能发生异常的程序代码放置在try程序块中。程序运行过程中,如果该程序块中没有出现任何异常,将正常执行,后面的代码各catch块将不起任何作用。如果该程序块内的代码有异常,系统将终止try程序代码块的执行,自动跳转到所发生的异常类对应的catch块,执行该块中的代码。
(2) 一个try程序可以对应多个catch块,用于对多个异常类的进行捕捉和处理。如果要捕捉的诸类之间没有父子继承关系,各类的catch块顺序无关紧要。但是如果它们之间有父子继承关系,则应该将子类的catch块放置到父类的catch块之前。
(3) 上述结构中的finally块是可选项,如果包含有finally块,无论是否发生异常,finally块的代码都要执行。若没有异常发生,当执行完try程序快内的代码后,将执行finally块。若出现了异常,执行完对应异常类的catch块后,将执行finally块。所以finally块是该结构的统一出口,一般用来进行“善后处理”,例如释放不再使用的资源、关闭使用完毕的文件。