捕获异常
- 如果在执行 try 块的过程中没有出现异常,则跳过所有的 catch 子句。
- 如果 try 块中的某条语句抛出一个异常,Java 就会跳过 try 块中剩余的语句,然后开始查找处理这个异常的代码的过程。 处理这个异常的代码称为异常处理器。可以从当前的方法开始,沿着方法调用链,按照异常的反向传播方向找到这个处理器。
- 从第一个到最后一个逐个检査 catch 块,判断在 catch 块中的异常类实例是否是该异常对、象的类型。 如果是, 就将该异常对象赋值给所声明的变量,然后执行 catch 块中的代码。
- 如果没有发现异常处理器,Java 会退出当前方法,并把异常对象传递给调用这个方法的方法,继续同样的过程来查找处理器。
- 如果在调用的方法链中找不到处理器,程序就会终止并且在控制台上打印出错信息。
- 像这样,寻找处理器的过程称为捕获一个异常。
上塑造型
- 从一个通用的父类可以派生出各种异常类。
- 如果一个catch块可以捕获一个父类的异常对象,它就能捕获那个父类的所有子类的异常对象。
如:如果catch后使用了Exception类型,那么该catch块就可以处理所有类型的Exception类对象。
在这种情况下,用Exception类的句柄引用了实际异常类的对象,这在面向对象程序设计
中,称为上溯造型。上溯造型永远是类型安全的。
catch中异常被指定的顺序是非常重要的
如果父类的 catch 块出现在子类的catch 块之前, 就会导致编译错误。因为子类的catch块永远也没有机会运行,错误提示的英文是:
Unreachable catch block for RuntimeException.
It is already handled by the catch block for Exception
即:catch后的异常类分别是Exception和RuntimeException,那么必须把RuntimeException的catch块放在Exception的catch块之前。
如果要对多个异常做同样的处理
则可以使用 多捕获特征 (multi-catch feature )来简化异常的代码编写
catch (Exceptionl | Exception2 |… | Exceptionk ex){ // 处理上述异常的代码}
每个异常类型使用竖线 (|) 与下一个分隔。如果其中一个异常被捕获,就会执行异常处理的代码。
注意!
用竖线 (|) 隔开的多个异常类之间不能有继承关系,否则会产生编译错误
异常对象包含了关于异常的有价值的信息。
可以利用下面这些 java.lang.Throwable 类中的实例方法获取有关异常的信息:
1、void printStatckTrace() 方法:在控制台上打印栈跟踪信息;
2、 stackTraceElement [] getStatckTrace()方法:提供编程的方式,来访问由 printStackTrace()打印输出的栈跟踪信息;
3、String getMessage() 方法:返回描述该异常对象的信息;
4、 String toString() 方法:返回三个字符串的连接,(1)异常类的全名; (2)” : “(一个冒号和空白)(3) getMessage()。
finally
有时候, 不论异常是否出现或者是否被捕获,都希望执行某些代码
try { // 可能会产生异常的代码} catch (Exception e) { // 异常处理代码} finally { // finally 代码}
在任何情况下,finally 块中的代码都会执行,不论 try 块中是否出现异常或者是否被捕获
特别的是
即使在到达 finally 块之前有一个 return 语句,finally 块还是会执行。
以使用JDBC来访问关系数据库为例,在执行完相应的SQL语句之后,一定要在finally子句中关闭连接对象,否则后续的程序将无法获得连接对象,从而抛出SQLException异常