try-finally 和 try-catch-finally 语句
try...catch...finally 语句将异常处理与清理代码结合在一起。finally 块包含将在所有情况下执行的代码。这使它们适用于资源管理和其他类型的清理。
尝试,终于
这是一个更简单(try...finally)形式的例子:
try {
doSomething();
} finally {
cleanUp();
}
try...finally 的行为如下:
- 执行
try块中的代码。 - 如果
try块没有抛出异常:- 执行
finally块中的代码。 - 如果
finally块抛出异常,则传播该异常。 - 否则,控制传递到
try...finally之后的下一个语句。
- 执行
- 如果 try 块中抛出了异常:
- 执行
finally块中的代码。 - 如果
finally块抛出异常,则传播该异常。 - 否则,原始异常继续传播。
- 执行
finally 块中的代码将始终执行。 (唯一的例外是如果调用 System.exit(int),或者如果 JVM 发生混乱。)因此,finally 块是始终需要执行的正确位置代码; 例如关闭文件和其他资源或释放锁。
try-catch-终于
我们的第二个例子展示了 catch 和 finally 如何一起使用。它还说明清理资源并不简单。
// This code snippet writes the first line of a file to a string
String result = null;
Reader reader = null;
try {
reader = new BufferedReader(new FileReader(fileName));
result = reader.readLine();
} catch (IOException ex) {
Logger.getLogger.warn("Unexpected IO error", ex); // logging the exception
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException ex) {
// ignore / discard this exception
}
}
}
在这个例子中,try...catch...finally 的一整套(假设的)行为太复杂了,不能在这里描述。简单的版本是 finally 块中的代码将始终执行。
从资源管理的角度来看这个:
- 我们在
try块之前声明资源(即reader变量),以便它将在finally块的范围内。 - 通过放置
new FileReader(...),catch能够处理打开文件时抛出的任何IOError异常。 - 我们需要在
finally块中使用reader.close(),因为我们无法在try块或catch块中拦截一些异常路径。 - 但是,由于在初始化
reader之前可能会抛出异常,我们还需要一个明确的null测试。 - 最后,
reader.close()调用可能(假设)抛出异常。我们并不关心这一点,但如果我们不在源头捕获异常,我们需要在调用堆栈中进一步处理它。
Version >= Java SE 7
Java 7 及更高版本提供了另一种 try-with-resources 语法 ,可显着简化资源清理。