异常分类
如图是Java异常层次结构的一个简化图:

所有的异常都由Throwable继承而来,之后分为Error和Exception两部分。
Error
Error类层次结构描述了Java运行时系统内部错误和资源耗尽错误。应用程序不应该抛出
这种类型的错误。对于这种错误我们无能为力,因此我们不需要关注这种错误。
Exception
根据程序是否有问题可以把Exception分成两类:由程序错误导致的异常属于RuntimeException;由
像I/O错误这类和程序无关的问题导致的异常属于其他异常。可以说,如果出现了RuntimeException异常,
那么就一定是你的问题。
Java语言规范将派生于Error和RuntimeException的所有异常称为非受查异常,所以其他的异常称为
受查异常。
异常抛出的情况
- 调用一个抛出受查异常的方法
- 程序运行过程发现错误,并利用
throw语句抛出一个受查异常 - 程序出现错误
- Java虚拟机和运行时库出现内部错误报告
抛出异常
关键字throws或throw用来抛出异常,示例:
1 | public void deposit(double amount) throws RemoteException |
注意:
- 如果在子类中覆盖了超类的一个方法,子类方法中声明的受查异常不能比超类方法中声明的异常更通用。如果超类
方法没有抛出任何受查异常,子类也不会抛出任何受查异常。 - 一旦方法抛出异常,这个方法就不可能返回到调用者
创建异常类
1 | //继承检查异常,抛出需要检查 |
运行结果:
1 | MyException: 出了什么错 |
捕获异常
使用 try 和 catch 关键字可以捕获异常。try/catch 代码块放在异常可能发生的地方。
try/catch代码块中的代码称为保护代码,使用 try/catch 的语法如下:
1 | try |
多重捕获块
一个 try 代码块后面跟随多个 catch 代码块的情况就叫多重捕获
多重捕获块的语法如下所示:
1 | try{ |
可以在 try 语句后面添加任意数量的 catch 块。
如果保护代码中发生异常,异常被抛给第一个 catch 块。
如果抛出异常的数据类型与 ExceptionType1 匹配,它在这里就会被捕获。
如果不匹配,它会被传递给第二个 catch 块。
如此,直到异常被捕获或者通过所有的 catch 块。
java7以后可以放在一个catch中,例如:
1 | try{ |
注意:只有当捕获的异常类型彼此之间不存在子类关系时才需要这个特性
异常方法
Throwable 类的主要方法:
1 | public String getMessage() |
finally
finally 关键字用来创建在 try 代码块后面执行的代码块。
无论是否发生异常,finally 代码块中的代码总会被执行。
在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。
finally 代码块出现在 catch 代码块最后,语法如下:
1 | try{ |
注意:当finally子句包含return语句时,在方法返回前,finally子句的内容
会被执行,这里的return语句的返回值会覆盖原始的返回值,例如:
1 | public static int f(int n){ |
如果调用f(2),那么try语句块的计算结果为r = 4,并执行return语句。
然而,在方法真正返回时,还要执行finally子句。finally子句使得方法返回
0,覆盖了原来的方法。
带资源的try
语法:
1 | try(Resure res = ....){ |
使用带资源的try语句,不用自己关闭资源。