Java提供了一套异常处理机制,用异常来表示可能出现的各种错误。异常是一种类,继承自Throwable类。Throwable类有两个子类体系,Error类和Exception类,Error类表示非常严重、无法处理的错误,而Exception类表示可以被捕获并处理的错误。
1 Error
例如:内存耗尽、栈溢出、类无法加载等。
2 Exception
分为RuntimeException类及其子类、非RuntimeException类及其子类两大类。
Error和RuntimeException及其子类无需被捕获,而非RuntimeException类及其子类错误必须被强制捕获。
3 异常的抛出及捕获
只要是方法声明的Checked Exception(受检异常),不在调用层捕获,也必须在更高的调用层捕获。所有未捕获的异常,最终也必须在main()方法中捕获,main()方法也是最后捕获Exception的机会。如果没有在main内部捕获错误并处理(不推荐捕获到错误之后不进行处理),而在声明main方法时抛出了Exception,一旦发生错误,程序会立即退出。
3.1 抛出异常
系统自动抛出异常:在程序的运行过程中,发生了异常,系统会自动抛出。
主动抛出异常:在方法中,当发生某个事件,创建一个异常实例,用throw
语句抛出。
抛出可能存在的异常:当我们不确定某个方法是否会发生异常,我们在声明方法时用throws
语句抛出可能会发生的异常。
3.2 捕获异常
将可能发生异常的语句放在try { ... }
当中,用catch
去捕获异常。如果可能发生多种异常,可以使用多catch语句,每一个catch语句捕获一种异常并进行处理。需要注意的是子类异常需要写在父类异常的前面,否则永远都捕获不到子类异常。
finally { ... }
语句,无论是否发生异常都会执行,在try语句和catch语句之后执行。可写可不写。
3.3 受检异常和运行时异常
受检异常(Checked EXception)是指可以被调用方处理或恢复的异常,Java强制要求捕获此种异常,否则编译就无法通过。例如:当打印机执行打印功能时,没有墨水了,发生异常,调用打印程序的调用方捕获该异常,并提示使用者添加墨水,待添加墨水之后,打印继续。
运行时异常(RuntimeException)是指调用方无法自行处理或恢复的程序错误,通常是存在于代码中。这种异常可以捕获也可以不捕获,都能通过编译。不建议捕获此种异常,因为可能导致程序继续执行,从而覆盖掉发生的程序错误,无法发现。建议不捕获此种异常,让程序退出,然后仔细地debug。例如:空指针、数组越界等。
4 自定义异常
我们定义自定义异常时,如果先定义一个“根异常”,其余业务异常由这个根异常派生出。通常根异常继承自RUntimeException,因为业务异常有些需要处理,而有些不必处理。