程序运行时,可能会发生各种错误,一些错误是可以避免的,还有些错误是随机出现的且不可避免,一个健壮的程序必须能够处理这些错误;

Java内置一套异常处理机制,使用异常来表示错误;

异常是一种类,本身带有类型信息,可以在任何地方抛出,但抛出以后需要在上层捕获;

 

异常

所以的异常类都是Java.lang.Exception类的子类,Exception类是Throwable类的子类;

Throwable类继承自Object类,它有两个子类:Error类和Exception类,Error表示严重的错误,不在程序的处理范畴,而Exception表示异常,需要被捕获并处理;

 

Exception分为两个类:运行时异常(RuntimeException)、非运行时异常(包括IOException);

 

Java规定必须捕获的错误:Exception类及其子类这样的检查性异常,但不包括RuntimeException类及其子类;

Java规定不必捕获的错误:Error类及其子类,RuntimeExcepiton类及其子类;

 

捕获异常

使用try/catch关键字可用于捕获异常,try/catch代码块可以放在任何异常可能发生的地方;

try/catch代码块中的代码称为保护代码,语法如下:

try
{
   // 程序代码
}catch(ExceptionName e)
{
   //Catch 代码块
}

可能发生异常的代码要放在try语句块中,catch语句块则捕获异常;

当try语句块中发生一个异常时,catch语句块就会被检查,若发生的异常包含在catch块中,异常会被传递到该catch块中,就像传递参数到方法中一样;

 

多个捕获块

一个try代码块后面可以跟随多个catch代码块,每个catch代码块分别捕获对应的异常及其子类,这样的情况叫做多重捕获;

try{
   // 程序代码
}catch(异常类型1 异常变量名1){
  // 程序代码
}catch(异常类型2 异常变量名2){
  // 程序代码
}catch(异常类型3 异常变量名3){
  // 程序代码
}

try语句块后可以跟随任意数量的catch语句块,但只有一个catch语句块能被执行;

当try语句块发生异常时,异常会先抛给第一个catch语句块,并从上往下逐个匹配,当抛出异常的类型与某个catch语句块的异常类型匹配时,异常就会在这个catch块被捕获,并不再继续匹配;

存在多个catch语句块时,catch语句块的顺序很重要,异常的子类必须放在前面;

 

finally关键字

虽然finally语句块是写在catch语句块后面的代码,但finally语句块中的代码在try代码块后面执行;

无论try语句块中的代码是否发生异常,finally代码块中的代码总会被执行;

try{
  // 程序代码
}catch(异常类型1 异常变量名1){
  // 程序代码
}catch(异常类型2 异常变量名2){
  // 程序代码
}finally{
  // 程序代码
}

 

注意事项

catch语句块不能独立于try语句块存在;

finally语句块不是强制要求的,是可选的;

try语句块也不能独立存在,后面不能既没有catch语句块也没有finally语句块;

try、catch、finally语句块之间不能添加任何代码;

 

捕获多个异常

若某些异常的处理逻辑相同,但异常之间不存在继承关系,那就需要编写多个catch语句块分别来捕获这些异常;

实际上,一个catch语句块也可以匹配多个非继承关系的异常,只需在这些异常之间使用 |

 

异常的传播

若一个方法没有捕获到一个检查性异常,那么该方法必须将异常抛出到上层调用方法,直到它被某个try/catch语句块捕获为止;

 

throws/throw关键字

可以通过将throws关键字放在方法签名的尾部来声明要抛出的异常,并在方法内部通过throw关键字抛出异常对象;

 

throws声明异常

当一个方法产生一个它不处理的异常时,就需要在方法的头部声明此异常以便将异常传递到方法外部进行处理;

一个方法可以声明并抛出多个异常,多个异常之间通过逗号分隔;

throws方法用于声明一个方法可能抛出的所有异常信息,但不代表异常一定会发生;

 

throw抛出异常

与thorws不同,throw用于直接抛出一个具体的异常,throw关键字后面跟随的就是一个异常类对象;

throw ExceptionObject;

当throw语句执行时,其后的语句将不再执行,此时程序转到上层调用程序执行,直到寻找到对应的catch语句处理异常或最外层的异常处理程序终止程序并打印调用栈情况;

 

try-with-resources

从JDK 7开始,可以使用try-with-resources来打开资源保证在语句执行完毕后每个资源都被自动关闭;

try (resource declaration) {
  // 使用资源
} catch (ExceptionType e) {
  // 异常块
}

try语句块声明和实例化资源,catch语句块处理关闭资源时可能引发的所有异常;

try-with-resources语句块中可以声明多个资源,使用多个资源时使用分号 ; 分隔各个资源;

 

自定义异常

在代码中抛出异常时,尽量使用JDK定义的异常类型,但我们也可以自己定义新的异常,需要记住的是自定义异常要是Throwable类的子类;

 

通用异常

Java中的异常还可以分为以下两种类型:

JVM异常:由JVM抛出的异常或错误,如NullPointerException;

程序级异常:由程序或API程序抛出的异常,如IllegalArgumentException;

 

NullPointerException

NullPointerException是最常出现的RuntimeException,NullPointerException即空指针异常;若一个对象为null,调用其方法或访问其字段就会产生此异常;

指针是属于C语言的概念,Java当中没有指针,Java中定义指向对象的变量实际上定义的是对象的引用,Null Pointer其实是Null Reference;