首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果从语句引发异常(初始化问题),try语句中的单个资源是否不会被关闭?

如果从语句引发异常(初始化问题),try语句中的单个资源是否不会被关闭?
EN

Stack Overflow用户
提问于 2018-11-01 03:05:43
回答 3查看 180关注 0票数 0

示例代码:

代码语言:javascript
复制
    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规范中,我理解了与“使用资源进行尝试”语句有关的以下要点

  • 如果一个资源无法初始化(即它的初始化器表达式抛出一个异常),那么到目前为止由try-with-resources语句初始化的所有资源都将被关闭。
  • 只有当资源初始化为非空值时,它才会关闭。
  • 如果从try块和try -语句都抛出异常,则该方法将抛出从try块抛出的异常;从try-语句抛出的异常将被抑制。

我有关于结束资源的问题,禁止与上述要点有关的例外情况。

1)上述示例代码用例(即资源未初始化)是否属于场景中的..resource将被关闭,而不管try语句是正常完成还是突然完成。这是否仅适用于在there语句中成功初始化的资源,并且try块中有一个错误?

2)如果在初始化资源时抛出异常(如示例),这将在初始化失败的情况下进行。在这种情况下,我们如何才能看到在try-with语句中抛出的异常(基本上只能在初始化过程中发生)?是关闭资源时引发的异常吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 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和显式资源闭包将一个具有资源的尝试语句表示为等效代码。这将是一个很好的资源,如果您正在努力尝试资源的语义。

票数 0
EN

Stack Overflow用户

发布于 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块抛出的异常将被抑制。

正如您所提到的,第二点中的“资源尝试”的例外是关闭资源。

票数 0
EN

Stack Overflow用户

发布于 2018-11-01 03:43:44

对旧语法的尝试资源是语法上的糖,使用旧语法编写它可以帮助您理解它所做的事情:

这类例子:

代码语言:javascript
复制
  try (AutoCloseable ac1 = ac1(); AutoCloseable ac2 = ac2()) {
    ac2.doWhatever();
  } catch (Exception e) { 
    fail(e);
  }

是这样改写的:

代码语言:javascript
复制
  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不会为空。
  • ac1ac2可以工作,在这种情况下,只有doWhatever()才会对失败负责。

如果ac2依赖于ac1,并且不在资源列表中,例如:

代码语言:javascript
复制
try (AutoCloseable ac2 = ac2(ac1())) {
  ...
}

然后,除非在AutoCloseable中关闭,否则ac1()构建的ac2::close不会被关闭。垃圾收集器不会调用ac1::close

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53094677

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档