Java异常处理
异常处理
编程错误可以分成三类:语法错误、逻辑错误和运行错误。
- 语法错误(也称编译错误)是在编译过程中出现的错误,由编译器检查发现语法错误。
- 逻辑错误指程序的执行结果与预期不符,可以通过调试定位并发现错误的原因。
- 运行错误是引起程序非正常中断的错误,需要通过异常处理的方式处理运行错误。
异常处理概念
为了避免程序非正常终止,保证程序的稳定性,需要使用异常处理的功能。
Java 提供了 try-catch 块的结构,用于捕获并处理异常。
该结构包括 try 块和 catch 块两部分,分别以关键字 try 和 catch 开始,catch 块包含特定异常类型的参数。
在 try 块中包含可能抛出异常的语句,当 try 块中的一个语句抛出异常且和 catch 块的参数的异常类型一致时,try 块中剩下的语句会被跳过,catch 块中的语句会被执行。
异常类型
Java 的异常类型是 Exception
类,它是 Throwable
类的子类。
Exception
类描述由程序和外部环境引起的错误,可以通过程序捕获和处理这些异常。Exception
类有多个子类,分别描述特定的异常。
RuntimeException
类是 Exception 类的子类,描述运行时异常。RuntimeException
类有多个子类,分别描述特定的运行时异常。
异常处理的操作
Java 的异常处理基于三种操作:声明异常、抛出异常和捕获异常。
声明异常
如果一个方法可能抛出异常,则需要在方法声明中使用关键字 throws 声明异常。如果一个方法可能抛出多种类型的异常,则需要在关键字 throws 之后依次列举可能抛出的异常类型。
抛出异常
如果程序检查到错误,则可以创建一个异常的实例并抛出该异常实例。使用关键字 throw 抛出异常。
需要注意声明异常的关键字 throws 和抛出异常的关键字 throw 的区别。
捕获异常
捕获异常通过 try-catch 块实现。
每个 catch 块包含一个特定异常类型的参数,如果需要捕获多种异常,则需要使用多个 catch 块,每个 catch 块分别包含一个特定异常类型的参数。
如果 try 块的执行过程中没有出现异常,则跳过 catch 块。
如果 try 块中的一个语句抛出一个异常,则跳过 try 块中剩下的语句,寻找可以处理该异常的代码,处理异常的代码称为异常处理器。具体而言,依次检查每个 catch 块,寻找可以处理该异常的 catch 块。
如果发现一个 catch 块的参数的异常类型和抛出的异常实例匹配,则将异常实例赋给该 catch 块的参数,执行该 catch 块的语句。
如果在当前方法中没有发现异常处理器,则异常没有被捕获和处理,退出当前的方法,并将异常传递给当前方法的调用者,继续寻找异常处理器。
如果一个 catch 块可以捕获一个父类的异常对象,则该 catch 块也能捕获该父类的所有子类的异常对象。
由于父类包含子类,因此需要注意 catch 块的顺序,子类异常对应的 catch 块必须出现在父类异常的 catch 块之前,否则会出现编译错误。
finally 子句
有时,无论异常是否出现或者被捕获,都需要执行一些语句,可以通过 finally 子句实现。使用关键字 finally 声明 finally 子句。
如果在 try-catch 块中包含 return 语句,finally 子句将在方法返回之前被执行。