Java的try-with-resources是否会捕获错误或只是异常?

时间:2016-11-02 11:52:26

标签: java exception junit exception-handling

我有一些junit测试可以创建一些也应该关闭的资源。

实现此逻辑的一种方法是使用@Before@After方法。

我所做的是将创建封装在某个实用程序类中以供重用。例如:

class UserCreatorTestUtil implements AutoClosable {
  User create() {...}
  void close() {...}
}

关键是对象要关闭,而不是需要记住在@After中关闭它。

用法应为:

@Test
void test() {
  try (UserCreatorTestUtil userCreatorTestUtil = new UserCreatorTestUtil()) {
    User user = userCreatorTestUtil.create();
    // Do some stuff regarding the user's phone
    Assert.assertEquals("123456789", user.getPhone());
  }
}

问题是junit的断言关键字会引发Error - 而不是Exception

try-with-resource" catch" Error并调用close方法?

*无法在try-with-resources documentation中找到答案。

5 个答案:

答案 0 :(得分:75)

它没有catch任何东西。但它会finally关闭所有资源。

finally阻止are run even when an Error is thrown

答案 1 :(得分:37)

基本 try-with-resources 语句的伪代码是(cf Java Language Specification §14.20.3.1):

final VariableModifiers_minus_final R Identifier = Expression;
Throwable #primaryExc = null;

try ResourceSpecification_tail
    Block
catch (Throwable #t) {
    #primaryExc = #t;
    throw #t;
} finally {
    if (Identifier != null) {
        if (#primaryExc != null) {
            try {
                Identifier.close();
            } catch (Throwable #suppressedExc) {
                #primaryExc.addSuppressed(#suppressedExc);
            }
        } else {
            Identifier.close();
        }
    }
}

正如您所看到的那样,Throwable不会Exception包含Error,而只会获取主要异常,以便将任何例外添加为已抑制的例外关闭资源时发生的事情。

您还可以注意到finally块中的资源已关闭,这意味着无论发生什么情况都会关闭(当然System.exit除外即使在抛出Error或任何Throwable子类的情况下,它也会终止当前运行的Java虚拟机。

答案 2 :(得分:13)

尝试资源不会捕获任何内容。

但是,您可以将catch块附加到try-with-resources块的末尾,以捕获您喜欢的任何类型的Throwable

try (UserCreatorTestUtil userCreatorTestUtil = new UserCreatorTestUtil()) {
  // ... Whatever
} catch (RuntimeException e) {
  // Handle e.
} catch (Exception | Throwable t) {
  // Handle t.
}

答案 3 :(得分:9)

try-with-resources背后的想法是确保资源应该关闭。

传统try-catch-finally语句的问题在于,假设您的try块抛出异常;现在通常你会在finally块中处理该异常。

现在假设finally块中也发生异常。在这种情况下,try catch抛出的异常是丢失finally块中生成的异常会被传播。

try {
    // use something that's using resource
    // e.g., streams
} catch(IOException e) {
   // handle 
} finally {
    stream.close();
    //if any exception occurs in the above line, than that exception
    //will be propagated and the original exception that occurred
    //in try block is lost.
}

try-with-resources中,资源的close()方法会自动调用,如果close()抛出任何异常,则finally的其余部分不会被触发到了,原来的例外就丢失了。

与此对比:

try (InputStream inputStream= new FileInputStream("C://test.txt")){
    // ... use stream
} catch(IOException e) {
   // handle exception
}

在上面的代码段中,自动调用close()方法,如果close()方法也生成了任何异常,则该异常将自动被抑制。

另请参阅:Java Language Specification 14.20.3

答案 4 :(得分:5)

对您的误解:尝试使用资源执行捕获

它最后最终 ,因此出现了"问题"无所谓。

有关详细信息,请参阅Google API client for PHP