异常的体系机构
Java
提供了丰富的异常类,而这些异常类之间又有这严格的继承关系。下面让我们看一下Java
中异常的体系结构。
首先,Java
将所有的不正常情况分为两种,一种是错误(Error)
,另一种就是我们所说的异常(Exception)
。
Error
错误是我发恢复,不能获取的,如系统崩溃,虚拟机错误,动态链接失败等。这会导致程序直接中断。
Exception
是我们常说的异常,他又大致分为两类,一类是运行时异常:RuntimeException
,另一类就是其他异常。因为RuntimeException
是由Java
虚拟机自动抛出并自动捕获,所以又叫非检查异常
。而另一类异常就不一样了,需要我们手动的捕获和处理异常,所以叫做检查异常
。
异常的捕获
介绍了异常的大概情况,下面我们啊来说说如何捕获处理异常。
try...catch...
首先,我们先想一下,如果没有我们使用最原始的解决异常是个什么办法:
if (异常1) {
处理
} else if (异常2) {
处理
} else {
处理
}
没错,就是一大长串的if...else
,对每种异常情况进行处理。所以这时我们就希望有一种更加强大的if块
,可以一下子表示所有的异常情况然后处理掉。这就有了我们的try...catch
。
try {
// 业务实现代码
...
} catch (Exception e) {
// 对异常的处理
}
如果try块
里的业务逻辑代码出现了异常,系统就会生成一个异常对象,然后将该对象提交给Java运行时环境
(throw),接着查找catch块
,如果找到了合适的catch块
,就将该异常对象交由该catch块处理。这个过程又叫做捕获(catch)异常
;如果找不到合适的catch块
,程序将退出。
多异常捕获
在Java7之前,对多种的异常只能使用多个catch
来进行捕获。
try {
// 业务实现代码
...
} catch (Exception1 e1) {
...
} catch (Exception2 e2) {
...
} catch (Exception3 e3) {
...
}
但是从Java7开始,多个异常可以使用同一个catch
来捕获。
注意:
1.多种异常类型之间用竖线“|”
隔开。
2.异常变量有隐式final
修饰,因此不能对异常变量重新赋值。
3.父类
异常要在子类
异常以后捕获。
finally回收资源
finally
,最终的,也就是我们处理完异常最后要做的事情。由于有时候我们会在try块
里面使用一些资源,这些资源最后也就在finally块
里被回收掉了。
try {
// 业务实现代码
} catch (Exception e) {
// 异常处理
} finally {
// 资源回收
}
当然了,如果你说我没有使用资源,不想在finally块
里做资源回收的操作,也是可以的。
异常链
首先说说为什么会有异常链这种东西。因为对于一个完整的应用而言,都是有比较严格的分层关系的,上层依赖下层的API
。而对于用户而言,我们不想看到底层的SQL异常
,同时也会使得系统不安全。所以这时我们就要将底层的异常捕获,然后再抛出一个新的业务异常,就可以在新的异常中给出用户比较友好的提示信息。
try {
// 业务逻辑的实现
} catch (SQLException e) {
// 记录原始异常
...
// 抛出新的异常
throw new AnotherException("访问数据库出现异常");
}
或者我们也可以这样处理异常:
try {
// 业务逻辑的实现
} catch (SQLException ex) {
// 记录原始异常
...
// 抛出新的异常
throw new AnotherException(ex);
}
这是由于Throwable
基类有了一个可以接受Exception
参数的方法。
总结
对于异常的了解,我还处于入门阶段,虽然平时的项目中也会遇到各种各样的异常,然后解决异常,但是也只能说是对异常有了一个了解。这里也是总结一下前人对于异常的经验吧。
1.不要过多的使用try...catch
,尽量使用逻辑去规避异常。
2.多重catch
块后面,最好再有个catch块用来捕获Exception异常
,防止遗漏。
3.尽量去处理异常,不要只是简单的使用printStackTrace()
打印异常。
相信随着编程经历的丰富,我对于异常的理解也会有更进一步的提升。期待自己的Java 异常进阶
。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。