3 回答
TA贡献1811条经验 获得超6个赞
1) 上面的示例代码情况(即资源初始化失败)是否不属于这种情况..无论try语句是正常完成还是突然完成,资源都将被关闭。这是否仅适用于在 try with resources 语句中成功初始化的资源并且 try 块中存在错误?
目前尚不清楚您所引用的“资源将被关闭,无论 try 语句是正常完成还是突然完成”。尽管如此,如果资源规范中的资源尝试初始化引发异常,则不会,该资源不会关闭,因为它没有初始化为非空值(您的第二个要点,它是 JLS 文本的摘录) .
如果资源规范中有多个资源,那么有可能在其中之一的初始化抛出之前先初始化一些资源;在这种情况下,那些成功初始化为非空值的将被关闭。
2) 如果在初始化资源时抛出异常(如示例),则属于初始化不成功的情况。在这种情况下,我们如何遇到 try-with-resources 语句中抛出异常的场景(基本上只能在初始化期间发生)?是关闭资源时抛出的异常吗?
try-with-resources 语句是一个复合语句,包含从初始try
关键字到相关块的所有内容,并包括任何catch
and 和finally
子句。主要重点是在try
块内部抛出异常的情况下正确清理。规范中关于资源初始化期间发生异常情况的位可以理解为N -resource try-with-resources 语句和N 个嵌套的单资源 try-with-resources 语句之间的等效性。
注意,那就是,在JLS礼物翻译一试,与资源语句为等效代码使用传统try
/ catch
/finally
和明确的资源闭合。如果您正在为 try-with-resources 的语义而苦苦挣扎,那将是一个值得考虑的好资源。
TA贡献1865条经验 获得超7个赞
1) 是的。如果资源初始化成功并且 try 块有异常,则资源将被关闭,就像我们在 finally 块中没有 try with resource 一样。
2)文档说(很少修改):
没有try with resource,如果在一个方法中,read()和close()(在finally块中)都抛出异常,则该方法抛出finally块中抛出的异常;从 try 块抛出的异常被抑制。相比之下,使用try with resource,如果try块和try-with-resources语句都抛出异常,则该方法抛出try块抛出的异常;从 try-with-resources 块抛出的异常被抑制。
正如您所提到的,第二点中 try-with-resource 的异常将来自关闭资源。
TA贡献1868条经验 获得超4个赞
在尝试与-资源是在旧的语法和使用旧的语法,可以帮助你了解它写它的语法糖:
这种例子:
try (AutoCloseable ac1 = ac1(); AutoCloseable ac2 = ac2()) {
ac2.doWhatever();
} catch (Exception e) {
fail(e);
}
改写成这样:
AutoCloseable ac1 = null;
try {
ac1 = ac1();
AutoCloseable ac2 = null;
try {
ac2 = ac2();
ac2.doWhatever();
} catch (Exception e) {
fail(e);
} finally {
if (ac2 != null) ac2.close();
}
} catch (Exception e) {
fail(e);
} finally {
if (ac1 != null) ac1.close();
}
编译器可能会优化代码:
只能有一个 finally 块,它可能会将两者合并。
使用一些合成函数来处理相同的捕获。
如果您有兴趣,E. Mandrikov 的这个演示文稿解释了编译器的作用以及它如何成为代码覆盖率的难题。
如您所见,它可能在初始化部分失败:
ac1
初始化可能会失败,在这种情况下,变量将是null
(默认值)。ac2
初始化可能会失败,ac1
不会为空。ac1
并且ac2
可能工作,在这种情况下,只有doWhatever()
将负责失败。
如果ac2
取决于ac1
,并且不在资源列表中,例如:
try (AutoCloseable ac2 = ac2(ac1())) { ...}
然后,AutoCloseable
构建由ac1()
将不会关闭,除非它被关闭了ac2::close
。并且垃圾收集器不会调用ac1::close
.
添加回答
举报