java - 返回尝试资源。这是 JVM 的正确行为吗?

标签 java jvm specifications try-with-resources

在下面的代码示例中,我希望 1 作为方法 testM() 的返回值。但由于 TestAutoCloseable.close() 方法中的异常,我得到了意外的行为。

我的问题是:“这是 JVM 的正常行为吗?”

public static void main(String[] args) {
    ProgrammerTwo programmerTwo = new ProgrammerTwo();
    System.out.println(programmerTwo.testM());
}

int testM() {
    try (TestAutoCloseable closable = new TestAutoCloseable()) {
        System.out.println("Do first return");
        return 1;
    } catch (IOException e) {
        System.out.println("handled");
    }
    System.out.println("Do something, that shouldn't do if first return have happened");
    return 2;
}

static class TestAutoCloseable implements AutoCloseable {

    @Override
    public void close() throws IOException {
        throw new IOException();
    }
}

因为如果这是正常行为,我们不应该在 try with resources 语句中使用 return 或 break 语句。它应该是反模式。

最佳答案

有关 try-with-resources 语句如何工作的详细信息位于 this section来自 JLS。在您的情况下,它是一个 扩展 try-with-resources 因为它有一个 catch 子句,如下面的引用中所定义(请注意突出显示的声明在最后)。

A try-with-resources statement with at least one catch clause and/or a finally clause is called an extended try-with-resources statement.

The meaning of an extended try-with-resources statement:

try ResourceSpecification
     Block
[Catches]
[Finally]

is given by the following translation to a basic try-with-resources statement nested inside a try-catch or try-finally or try-catch-finally statement:

try {
  try ResourceSpecification          <--- exception thrown in this basic try-with-resources
      Block
}
[Catches]
[Finally]

The effect of the translation is to put the resource specification "inside" the try statement. This allows a catch clause of an extended try-with-resources statement to catch an exception due to the automatic initialization or closing of any resource.

这意味着关闭资源发生在外部 try block 的主体内,导致抛出异常并在 catch 中进行处理> block ,控制权恢复到扩展 try-with-resources 语句之后的语句。

实际上,整个方法 testM 相当于:

int testM() {
    try {
       final TestAutoCloseable closable = new TestAutoCloseable();
       Throwable #primaryExc = null;
       try {
           System.out.println("Do first return");
           return 1;
       } catch (Throwable #t) {
           #primaryExc = #t;
           throw #t;
       } finally {
           if (closable != null) {
              if (#primaryExc != null) {
                 try {
                    closable.close();
                 } catch (Throwable #suppressedExc) {
                    #primaryExc.addSuppressed(#suppressedExc);
                 }
              } else {
                 closable.close();
              }
          }
       }
    } catch (IOException e) {
       System.out.println("handled");
    }
    System.out.println("Do something, that shouldn't do if first return have happened");
    return 2;
}

关于java - 返回尝试资源。这是 JVM 的正确行为吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39595742/

相关文章:

java - 除了我们的声音之外,向 freeTTS 添加新的声音

java - 读取 JSON 子对象

java - 在 RCP 应用程序中运行测试时,SWTBot 使 JVM 崩溃

jvm - 为什么我们不能在不初始化的情况下用 get 覆盖 val 属性作为 var 呢?

javascript - 什么是 ECMAScript 6 WeakMaps?

spring - JPA2 Criteria-API : select. .. in(从位置选择)

sql - JDBC 规范是否阻止将 '?' 用作运算符(引号外)?

java - JTable 不显示列名称

java - Android ListView NullPointerException 使用 pulldowntoRefresh?

garbage-collection - Java中的总内存是如何计算的