设计一个严谨的程序是一项繁琐的工作。各种各样的情况都应当被充分考虑。如果不采用异常处理方法,而按照一般的程序设计方法,则基本上只能逐个分析在程序中可能出现的各种异常情况,并在程序的相应位置立即作出适当的处理。这样,程序的选择分支语句可能会大量存在,是的程序结构变得非常复杂。另外,检查各种异常情况是否被处理完全也是非常繁琐的工作。各种分支情况处理不完整是引起程序不稳定的重要因素之一。采用异常处理,可以简化这种处理过程,是程序具有统一的处理模式,即可以将各种异常情况集中统一处理。
异常及其种类
异常(Exception)是正常程序流程所不能处理或没有处理的异常情况或异常事件。异常可以分为两大类:受检异常(Checked Exception)与非受检异常(Unchecked Exception)。受检异常在编译时就能被Java编译器所检测到;而非受检异常则不能在编译时检测到。非受检异常包括运行时异常(Runtime Exception)和错误(Error)。运行时异常只能在程序运行时被检测到,如:除数为0。另外,错误异常时不能在编译时被检测到的。Java语言所定义的错误异常一般指各种致命性错误。一旦发生“错误”,则很难或根本就不可能由程序来恢复或处理。
在Java语言中,异常是以类的形式进行封装的。程序可以处理的异常对应的类是java.lang.Exception及其子类,错误异常对应的类是java.lang.Error及其子类,运行时异常对应的类是java.lang.RuntimeException及其子类,其中,类java.lang.RuntimeException是类java.lang.Exception的子类。在类java.lang.Exception的子类中,除了类java.lang.RuntimeException及其子类之外,都是受检异常所对应的类。这些类都是类java.lang.Throwable的子类。
异常产生
异常可以由Java虚拟机在执行程序时自动发现并产生,也可以在程序中显式生成。这种显式生成异常的方法称为抛出异常。抛出异常可以利用throw语句,其格式为
throw java.lang.Throwable类型的变量;
异常处理
处理异常的方式有两种:捕捉异常方式和转移异常方式。
- 捕捉异常方式是通过try-catch-finally结构处理异常:
try
{
//可能会产生异常的语句序列
}
catch(Exception e1)
{
//语句序列
}
catch(Exception e2)
{
//语句序列
}
finally
{
//语句序列
}
其中catch语句块与finally语句块不一定要同时存在,其中只要有一个语句块存在就可以了。在try-catch-finally结构中,可以存在多个catch语句块,表示可以捕捉多种异常。当try语句块有异常产生时,中断try语句块剩余的语句的执行,并产生该异常所对应的实例对象,而且try语句块剩余的语句一般将不会被执行。在try-catch-finally中,finally语句块一般总是会被执行,不管有没有异常产生。即使在try语句块或catch语句块中包含return语句,finally语句块也会被执行到。在try-catch-finally结构中,如果执行到在try语句块或catch语句块中的return语句,则先运行finally语句块,再运行return语句。如果执行到在try语句块或catch语句块中的语句”System.exit(0)”,则直接退出程序,即这时finally语句块将不会被执行到。
-
转移异常方式:
如果某个成员方法的方法体中可能会发生受检异常,则该成员方法必须处理这些受检异常。如果不想再该成员方法中立即处理该异常,则可以将该异常转移到调用它的上一层方法。转移异常的格式是:
[方法修饰词列表] 返回类型 方法名(方法的参数列表) throws 异常类型列表
{ //方法体 }
在异常类型列表中应当罗列所有需要转移的受检异常类型。如果存在多种异常类型,则相邻两个异常类型之间用逗号隔开。
自定义异常类型
创建自定义异常类就是编写java.lang.Exception类的子类。新定义的异常类在异常处理中的使用方法与其他异常类基本没有区别。
参考文献:《Java程序设计教程》(第2版) 雍俊海