示例代码:
class TestCharStream {
public static void main(String[] args){
// Assume specified file is not available in the location
try (Reader reader = new FileReader("C:\\TestData\\test123.txt")) {
System.out.println("Entered Try block");
int content;
while ((content = reader.read()) != -1) {
System.out.print((char) content);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}由于该文件不可用,将引发“‘FileNotFoundException”,资源将无法初始化。
从Java SE7规范中,我理解了与“使用资源进行尝试”语句有关的以下要点
我有关于结束资源的问题,禁止与上述要点有关的例外情况。
1)上述示例代码用例(即资源未初始化)是否属于场景中的..resource将被关闭,而不管try语句是正常完成还是突然完成。这是否仅适用于在there语句中成功初始化的资源,并且try块中有一个错误?
2)如果在初始化资源时抛出异常(如示例),这将在初始化失败的情况下进行。在这种情况下,我们如何才能看到在try-with语句中抛出的异常(基本上只能在初始化过程中发生)?是关闭资源时引发的异常吗?
发布于 2018-11-01 03:35:15
1)上述示例代码用例(即资源未初始化)是否属于场景中的..resource将被关闭,而不管try语句是正常完成还是突然完成。这是否仅适用于在there语句中成功初始化的资源,并且try块中有一个错误?
您所引用的“资源将被关闭,而不管try语句是否正常或突然完成”并不清楚。然而,如果资源规范中的资源初始化尝试抛出异常,则不会抛出异常,因为该资源没有被初始化为非空值(您的第二个项目点,这是JLS文本的摘录)。
如果资源规范中有多个资源,那么在初始化其中一个抛出之前,可以对其中一些资源进行初始化;在这种情况下,成功初始化为非空值的资源将被关闭。
2)如果在初始化资源时抛出异常(如示例),这将在初始化失败的情况下进行。在这种情况下,我们如何才能看到在try-with语句中抛出的异常(基本上只能在初始化过程中发生)?是关闭资源时引发的异常吗?
试探性资源语句是一个复合语句,包含从初始try关键字到关联块的所有内容,并包含任何catch和和finally子句。主要关注的是在从try块内部抛出异常时正确地清理。规范中有关异常在资源初始化期间发生的情况的比特可以从N资源尝试资源语句和N个嵌套的单资源尝试资源语句之间的等效性来理解。
还要注意的是,JLS使用传统的翻译 / catch / finally和显式资源闭包将一个具有资源的尝试语句表示为等效代码。这将是一个很好的资源,如果您正在努力尝试资源的语义。
发布于 2018-11-01 03:18:37
1)是。如果资源已成功初始化,并且try块有异常,则资源将被关闭,就像我们在“最后”块中不使用try资源时一样。
2)文件上写着(几乎没有修改):
如果在没有try with资源的情况下,如果在方法中,read()和close(在最后块中)都抛出异常,那么该方法将抛出从finally块抛出的异常;从try块抛出的异常将被抑制。与此形成对比的是,对于try with resource,如果从try块和try -语句都抛出异常,则该方法将抛出从try块抛出的异常;从try- with -resources块抛出的异常将被抑制。
正如您所提到的,第二点中的“资源尝试”的例外是关闭资源。
发布于 2018-11-01 03:43:44
对旧语法的尝试资源是语法上的糖,使用旧语法编写它可以帮助您理解它所做的事情:
这类例子:
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();
}编译器可能会优化代码:
如果您感兴趣,这个E. Mandrikov的介绍解释了编译器做了什么,以及代码覆盖率是如何让人头疼的。
如您所见,它可能在初始化部分失败:
ac1初始化可能失败,在这种情况下,变量将是null (默认值)。ac2初始化可能失败,ac1不会为空。ac1和ac2可以工作,在这种情况下,只有doWhatever()才会对失败负责。如果ac2依赖于ac1,并且不在资源列表中,例如:
try (AutoCloseable ac2 = ac2(ac1())) {
...
}然后,除非在AutoCloseable中关闭,否则ac1()构建的ac2::close不会被关闭。垃圾收集器不会调用ac1::close。
https://stackoverflow.com/questions/53094677
复制相似问题