finally 块的意义
Significance of finally block
Finally
块在Try...[Catch]...Finally
块中的意义是什么?
这不是代码吗
Resource r;
try{
r = new Resource();
r.methodThatThrowsException();
} catch (Exception e) {
e.printStackTrace()
} finally {
r.close()
}
相当于
Resource r;
try{
r = new Resource();
r.methodThatThrowsException();
} catch (Exception e) {
e.printStackTrace()
}
r.close()
?如果它们具有相同的范围,我会理解,但事实上我必须在 try 块之外定义 Resource r
才能在 finally 块中使用它,这意味着我认为使用 finally 块没有任何优势。
我错过了什么吗?有没有我没有想到的特定情况需要 Finally 块?
在这种情况下,它们是等效的,因为 (a) 代码捕获任何异常,包括抛出的运行时异常,以及 (b) catch 块不会重新抛出异常,因此执行会继续。
finally
块通常用于在 (a) 或 (b) 不成立的情况下确保资源释放。在较新的 Java 实现中,您应该尽可能使用 try-with-resources
。
不,这不等价。在第一个代码段中 r.close()
将 始终被调用 ,而在第二个代码段中 r.close()
可能不会被调用:
- 当 try 块抛出
Error
(当您使用断言并且断言失败时可能发生的情况) - 当异常处理程序抛出另一个异常时
为确保资源始终被释放 close()
方法应从 finally
个块中调用。
这两个代码片段不同:如果异常处理块在另一个异常中结束,第二个代码片段将不会关闭。
这是一个例子:
public static void one() throws Exception {
try {
System.out.println("One");
throw new Exception();
} catch (Exception e) {
System.out.println("Catch one");
if (2 != 3) throw new Exception(); // "if" silences compiler's check
} finally {
System.out.println("Finally one");
}
}
public static void two() throws Exception {
try {
System.out.println("Two");
throw new Exception();
} catch (Exception e) {
System.out.println("Catch two");
if (2 != 3) throw new Exception(); // "if" silences compiler's check
}
System.out.println("After two");
}
调用 one()
打印 Finally one
,而 After two
永远不会打印 (demo 1)。
finally
块在您捕获特定异常 (blindly catching Exception
is nearly always a bad idea) 时变得更加重要,因为 try
块可能会抛出您没有抛出的异常来绕过您的清理代码抓住。这是另一个例子:
public static void error() throws Exception {
try {
System.out.println("Try");
throw new Error();
} catch (Exception e) {
System.out.println("Catch");
throw new Exception();
} finally {
System.out.println("Finally");
}
}
此代码打印 Try
和 Finally
,中间没有 Catch
,因为 Error
没有被捕获在 catch
块中(demo 2).
不用说,如果您将清理代码放在 finally
块中,程序的人类读者将更容易找到您的清理代码。