Luoml's blog

java exceptions

Java异常体系

Java异常类层次结构如下:
Throwable

在Java中,所有异常都继承自ThrowableThrowable有两个重要子类:ErrorException

  • Error:程序无法处理错误
    如:OutOfMemoryError(内存溢出)、NoClassDefFoundError(类定义错误)等。
  • Exception:异常,程序可以处理
    Exception又分为运行时异常(RuntimeException)和非运行时异常
    也称之为不检查异常(Unchecked Exception)和检查异常(Checked Exception)。

    • 运行时异常
      包括RuntimeException类及其子类和错误(Error)
      如:NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等。
    • 非运行时异常(编译异常)
      RuntimeException以外的异常,必须处理,否则程序不能编译通过
      如:IOException、SQLException等。

异常处理机制

Java异常处理机制:抛出异常、捕捉异常。异常总是先被抛出,后被捕获。

捕获异常

try ... catch ... finally

1
2
3
4
5
6
7
8
9
try {
// 可能会发生异常的程序代码
} catch(XXXException e) {
// 捕获异常XXXException
} catch(Exception e) {
// 捕获异常Exception
} finally {
// 无论是否发生异常,都将执行的语句块
}
  • try块
    用于捕获异常,其后可以跟零或多个catch块,如果没有catch块,则必须跟一个finally块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//写法一
try {

} catch (Exception e) {

}

//写法二
try {

} catch (Exception e) {

} finally {

}

//写法三
try {

} finally {

}
  • catch块
    用于处理try捕获到的异常,在JDK7及更高版本,可通过|来处理多个异常
1
2
3
catch(IOException | SQLException e) {
throw e;
}
  • finally块
    无论是否捕获或处理异常,finally块里的语句都会被执行。当try或catch中遇到return语句时,finally块将在方法返回前被执行。
1
2
3
4
5
以下4种特殊情况下,finally块不会被执行:
1. 在finally块中发生了异常
2. 使用了System.exit()退出程序
3. 程序所在线程死亡
4. CPU关闭(如:计算机断电等)

抛出异常

声明throws抛出异常

如果一个方法可能出现异常,但又没有能力处理,可以在方法声明处使用throws子句来声明抛出异常。(多个异常用逗号分隔)

1
2
3
returnType methodName() throws IOException, SQLException, ... {

}

抛出异常原则:

  • 如果是Unchecked Exception,即Error、RuntimeException及其子类,那么可以不使用throws关键字来声明要抛出的异常,编译仍能通过,但在运行时会被系统抛出。
  • 必须声明方法可抛出的异常为Checked Exception。
  • 仅当抛出了异常,该方法的调用者才必须处理或重新抛出异常。

使用throw抛出异常

throw总是出现在函数体中,用来抛出Throwable类型的异常。程序会在throw语句后立即终止,其后语句不会执行,然后在包含它的所有try块从里向外寻找与其匹配的catch子句。

1
throw new XXXException("exception msg");

参考


Fork me on GitHub