java提供了异常处理机制来帮助程序员检查可能出现的错误,java中将异常封装到一个类中,出现错误时,就会抛出异常。
【异常】:
异常是指程序在允许时产生的错误,例如进行除法运算时,若除数为0时,则运行就会抛出算数异常;若对一个值为null的引用变量进行操作,则会抛出空指针异常;若访问一个大小为2的一维数组中的第3个元素,则会抛出数组下标越界的异常。
java中异常也是通过一个对象来表示的,程序运行时抛出的异常,实际上就是一个异常的对象。该对象不仅封装了错误信息,还提供了一些处理方法,如getMessage()方法获取异常信息,printStackTrace()方法输出对异常的详细描述。
对于可能出现的异常,都需要预先进行处理,保证程序的有效运行,否则程序就会出错。对于这些异常,有的需要程序员进行捕获处理或者声明抛出,称为“受检查异常”;有的是由java虚拟机自动捕获处理,称为“运行时异常”或“不受检异常”
【异常处理】:
异常产生后,如不进行任何处理,则程序就会被终止,为了保证程序有效的执行,需对产生的异常进行相应的处理。若某个方法抛出异常,既可以在当前方法中进行捕获,然后处理该异常,也可以将异常向上抛出,有方法的调用者来处理。
【try..catch语句】
对于发生异常的代码,可以通过“try..catch”语句进行捕获,在try语句中编写可能会发生异常的代码,然后在catch语句中捕获执行这些代码时可能发生的异常。
一般格式:
try{
可能产生异常的代码·
}catch(异常类 异常对象){
异常处理代码
}
try语句中的代码可能同时存在多种异常,那么到底捕获的哪一种类型的异常,是由catch语句中的“异常类”参数来指定的,catch语句类似于方法的声明,包括一个异常类型和该类的一个对象,异常类必须是Throwable类的子类,用来指定catch语句要捕捉的异常,异常类对象可在catch语句中被调用,如调用对象的getMessage()方法获取对异常的描述信息。
将一个字符串转为整型,可以通过Integer类的parseInt()方法来实现,当该方法的字符串参数包含非数字字符时,parseInt()方法会抛出异常,Integer类的parseInt()方法声明如下:
public static int parseInt(String s) throws NumberFormatException{...}
代码中通throws语句抛出了NumberFormatException异常,所以在应用parseInt()方法时可通过“try...catch”语句来捕获异常,从而进行相应的异常处理。
例如,将字符串“24L”转换为integer类型,并捕获转换中产生的数字格式异常,可以使用如下代码:
try{
int age=Integer.parseInt("24L");
System.out.println("打印1"); //抛出异常
}catch(NumberFormatException e){ //捕获异常
System.out.println("年龄请输入整数");
System.out.println("错误:"+e.getMessage());
}
System.out.println("打印2");
执行到int age=Integer.parseInt("24L"); 就会抛出异常,然后直接被catch语句捕获,成语流程跳转到catch语句内继续执行,所以“打印1”的语句不会执行,而异常处理完成之后,会继续执行try...catch之后的代码,也就是“打印2”。
(注):如果不知道代码抛出的是哪种异常,可以指定它们的父类Throwable或Exception。
在try...catch语句中,可以存在多个catch语句块
一般格式:
try{
可能产生异常的代码
}catch(异常类1 异常对象){
异常1处理代码
}catch(异常类2 异常对象){
异常2处理代码
}
...//其他catch语句块
代码中的每一个catch都用来捕获一种类型的异常,若try语句块中的代码发生异常,则会由上而下依次来查找能够捕获该异常的catch语句块,并执行该catch语句的代码。
在使用多个catch语句捕获try语句块中的代码抛出异常时,需注意catch语句的顺序,如果多个catch语句所要捕获的异常类之间具有继承关系,则用来捕获子类的catch语句要放在捕获父类catch语句的前面,否则,异常抛出,先由捕获父类异常的catch语句捕获,而捕获子类异常的catch语句将成为执行不到的代码,在编译时就会出错。
【finally子句的用法】:
finally要与try...catch语句一起使用,不管程序有无异常发生,并且不管之前的try...catch是否顺利执行完毕,最终都会执行finally语句块的代码,这使得一些不管在任何情况下都必须被执行的步骤被执行,从而保证程序的健壮性。
【使用throws关键字】:
若某个方法可能会发生异常,但是不想在当前方法中来处理这个异常,那么可以将这个异常抛出,然后在调用该方法的代码中进行异常的捕获以及处理。
所以将异常抛出,可以用throws关键字来实现,throws关键字通常被应用在声明方法中,用来指定方法可能抛出的异常,多个异常可以用逗号来分隔。
如果异常的类型是Erro和RuntimeException或是它们的子类,那么可以不使用throws关键字来声明。
将异常通过throws关键字抛给上一级,如果仍然不限处理这个异常,可以继续向上抛出,但是最终必须有能够处理这个异常的代码。
【使用throw关键字】:
区分throws和throw。与throws不同的是,throw用于方法体内,并且抛出一个异常类对象,而throws用在方法声明中。throw抛出异常后,同样需要使用try...catch语句,上述两张情况,若throw抛出的异常Error、RuntimeException或它们的子类,则无须使用throws关键字或者try...catch。
【使用异常处理语句的注意事项】:
在使用try...catch,finally,throw,throws关键字时,要注意:
(1)不能单独使用try,catch或finall语句块。
(2)try语句块后面既可以只使用catch语句块,也可以只是用finally语句,当它们一起使用时,可以存在多个catch语句块,但是只能有一个finally语句,并且finally只能在catch之后。
(3)try只与finally语句块使用时,可以使程序在发生异常后抛出异常,并继续执行方法中的其他代码。
(4)try只与catch语句使用时,可以使用多个catch语句来捕获try语句块的异常,异常发生后,java虚拟机会由上而下来检测当前catch语句块所捕获的异常是否与try语句块中的发生的异常匹配。如果匹配,则不再执行其他catch语句。如果多个catch语句块捕捉的是同种类型的异常,则捕获子类异常的catch语句要放在父类异常的前面,否则编译出错。
(5)在try语句中声明的变量时局部变量,只在当前try语句中有效,在其后面的catch,finally语句中其他位置不能访问该变量,但在try,catch,finall语句块之外声明的变量,可以在ry,catch,finall语句块之内使用。
(6)对于发生的异常,必须使用try...catch语句来捕获。或者通过throws语句向上抛出,否则出错。
(7)在使用throw语句抛出一个异常对象时,该语句后面代码将不会被执行。
(8)finally 执行的时机是在方法返回之前(try 或者 catch 中如果有 return 会在这个 return 之前执行 finally). 但是如果
finally 中也存在 return 语句, 那么就会执行 finally 中的 return, 从而不会执行到 try 中原有的 return。所以一般不建议在finally语句块中写return语句。
【非受查异常和受查异常】:
java语言规范将派生于 Error 类或 RuntimeException 类的所有异常称为 非受查异常, 所有的其他异常称为 受查
异常.如果抛出受查异常,则需要进行显示处理。