常用Exception类的子类:
异常类 |
描述 |
NullPointerException |
空指针异常 |
ArrayIndexOutOfBoundsException |
数组越界访问异常 |
ClassNotFoundException |
试图访问一个根本不存在的类 |
IOException |
输入/输出异常 |
NumberFormatException |
错误的类型转换异常 |
ArrayStoreException |
当向数组存入错误类型数据时 |
ArithmeticException |
除数为0的算术异常 |
Java提供了异常处理机制,通过面向对象的方法来处理异常。
在程序运行的过程中,如果发生了异常,则该程序(或Java虚拟机)生成一个代表该异常类的对象(包含该异常的详细信息),并把交给运行时系统;
运行时系统从生成对象的代码开始,沿方法的调用栈逐层回溯查找,直到找到包含相应处理代码的方法,并把异常对象交给该方法,来处理这一异常。
使用try-catch-finally语句捕获和处理异常
格式:try{
//产生异常的语句
}catch(异常类1 变量){
//异常处理代码
}catch(异常类2 变量){
//异常处理代码
}[finally{
}]
try语句块
将程序中可能出现异常的代码放入try块中。
当try块中有语句引发异常时,系统将不再执行try块中未执行的语句,而执行匹配的catch块。
如果try块中没有语句引发异常,则程序执行完try块中的语句后不执行catch块中的语句,即跳过catch语句,继续执行后面的程序。
catch块
每个try语句后面必须伴随一个或多个catch语句,用于捕捉try语句块所产生的异常并作相应的处理。
catch子句的目标是解决“异常”情况,并像没有出错一样继续运行。
多个catch块
一个catch块只能处理一类异常,当try块中的语句组可能抛出多种异常时,就需要有多个catch块来分别处理各种异常。
try{
int a=args.length; System.out.println("a=" + a);
int b=42/a; int c[]={1}; c[42]=99;
}catch(ArithmeticException e){
System.out.println("div by 0:" + e);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("array index oob:" + e);
}
一个异常对象能否被一个catch块接收主要看该异常对象与catch块中声明的异常类的匹配情况,当它们满足下面条件中的任一条时,异常对象将被接受:
异常对象是catch块中声明的异常类的实例;
异常对象是catch块中声明的异常类的子类的实例;
异常对象实现了catch块中声明的异常类的接口。
当使用多个catch块时,需注意catch子句排列顺序--先特殊到一般,也就是子类在父类前面。如果子类在父类后面,子类将永远不会到达。
try语句的嵌套
一个try语句可以在另一个try块内部----try语句的嵌套。
每次进入try语句,异常的前后关系都会被压入堆栈。如果一个内部的try语句不含特殊异常的catch处理程序,堆栈将弹出,下一个try语句的catch处理程序将检查是否与之匹配。
这个过程将继续直到一个catch语句匹配成功,或者是直到所有的嵌套try语句被检查耗尽。
如果没有catch语句匹配,Java的运行时系统将处理这个异常。
finally语句块
某些情况下,不管异常是否发生,都需要处理某些语句,那么就将这些语句放到finally语句块中。finally语句所包含的代码在任何情况下都会被执行。
一个try语句至少有一个catch语句或finally语句与之匹配,但匹配的catch可以有多个,而finally语句只能有一个,并且finally语句并非必须有的。
例8.7 finally的用法示例。main()方法中的语句为:
String[] friends={"Tom","葫芦娃","孙悟空"};
throw语句的使用
声明抛弃异常
如果一个方法中的代码在运行时可能生成某种异常,但是在本方法中不必要,或者不能确定如何处理此类异常时,则可以使用throws声明抛弃异常;
表明该方法中将不对此类异常进行处理,而由该方法的调用者负责处理;
即系统将在调用该方法的上层方法体内寻找合适的异常处理代码,而不再继续执行该方法的正常处理流程。
声明抛弃异常的格式
类型 方法名([参数表]) throws异常类型,…{
//方法体;
虽然Java的内置异常处理能够处理大多数常见错误,但用户仍需建立自己的异常类型来处理特殊情况。这时可以通过创建Exception的子类来定义自己的异常类。
格式:class 类名 extends Exception{
… …
}
在Java中,对异常进行处理需要考虑以下因素:
如果异常事件是在运行时产生的,并且在JDK API中没有与该异常事件相对应的异常对象,则应创建用户自定义类型的异常对象。
如果可以预测异常对象的类型并且该异常是在程序运行时发生的,则建议应用JDK API中定义的系统异常类型,并且可以抛出这种类型的异常对象由JVM处理。
如果不能确定异常对象的类型以及异常发生的时机,则应该采用系统类型异常对象并由JVM处理。
对应用程序设计失误导致的数组越界、非法变量等类型的异常,如果要全部捕获所有类型的异常对象,会增加系统开销,导致程序的运行效率降低,建议应用程序可以不对此类异常进行捕获,而交由JVM进行处理。
对于实现输入/输出处理、网络通讯和数据库访问功能的代码,必须进行异常对象的捕获和处理 。