1.处理异常
1.1异常分类
在Java程序设计语言中,异常对象都是派生于Throwable类的一个实例,所有的异常都是由Throwable继承而来,下一层立即分解为两个分支:Error和Exception。
Error类层次结构描述了Java运行时系统的内部错误和资源耗尽错误。
Exception类层次结构又分为两个分支:一个分支派生于RuntimeException;另一个分支包含其他异常。划分两个分支的规则是:由程序错误导致的异常属于RunException;而程序本身没有问题,但由于I/O错误这类问题导致的异常属于其他异常。
派生于RunException的异常包含下面几种情况:
(1)错误的类型转换。
(2)数组访问越界。
(3)访问空指针。
不是派生于RunException的异常包括:
(1)试图在文件尾部后面读取数据。
(2)试图打开一个错误格式的URL。
(3)试图根据给定的字符串查找Class对象,而这个字符串表示的类并不存在。
Java语言规范将派生于Error类或RuntimeException类的所有异常称为未检查(unchecked)异常,所有其他的异常称为已检查(checked)异常。
下面4种情况应该抛出异常:
(1)调用一个抛出已检查异常的方法,例如,FileInputStream构造器。
(2)程序运行过程中发现错误,并且利用throw语句抛出一个已检查。
(3)程序发现错误。
(4)Java虚拟机和运行库时的内部异常。
1.2.捕获异常
要想捕获一个异常,必须设置try/catch语句块。
try{
code
more code
more code
}
catch(ExceptionType e){
handler for this type
}
如果在try语句中的任何代码抛出一个catch子句中说明的异常类,那么
(1)程序将跳过try语句块的其余代码。
(2)程序将执行catch子句中的处理器代码。
如果try语句块中代码没有抛出任何异常,那么程序将跳过catch子句。如果方法中的任何代码抛出一个在catch子句中没有声明的异常类型,那么这个方法就会立刻退出(期待调用者为这种类型的异常设计了catch子句)。
finally子句
不管是否有异常被捕获,finally子句中的代码都被执行。
Graphics g = image.getGraphics():
try{
//1
code that might throw exceptions
//2
}
catch(IOException e){
//3
show error dialog
//4
}
finally{
//5
g.dispose();
}
//6
在上面这段代码中,有下列三种情况会执行finally子句:
(1)代码中没有抛出异常,程序首先执行try语句块中的全部代码,然后执行finally子句中的代码。执行标注1、2、5、6处。
(2)抛出一个在catch子句中捕获的异常。在上面的示例中就是IOException异常。程序将执行try语句块中的所有代码,知道发生异常为止。此时,将跳过try语句块中的剩余代码,转去执行与该异常匹配的catch子句中的代码,最后执行finally子句的代码。
如果catch子句没有抛出一个异常,程序将执行try语句块之后的第一条语句。在这里,执行标注1、3、4、5、6处的语句。
如果catch子句抛出了一个异常,异常将被抛回这个方法的调用者。在这里,执行标注1、3、5处语句。
(3)代码块抛出了一个异常,但这是异常不是由catch子句捕获的。在这种情况下,程序将执行try语句块中的所有语句,直到有异常被抛出为止。此时,将跳过try语句块中的剩余代码,然后执行finally子句中的语句,并将异常抛给这个方法的调用者。在这里,执行标注1、5处的语句。
try语句可以只有finally子句,而没有catch子句。