在try-with-resource中手动关闭

时间:2014-01-21 09:50:22

标签: java try-with-resources

让我们说我使用的是一个记录不完整的第三方库,其中没有源代码可用。其中一个库的方法接受InputStream来加载各种数据。

由于缺少文档,一旦用完它就不清楚该方法是否关闭了流,所以一种可能的解决方案可能就是试一试这个方法。 - 资源,只是为了安全起见。

不幸的是,Java规范(据我所知)没有提到如果在try-with-resource中手动关闭资源会发生什么。有人碰巧知道吗?

4 个答案:

答案 0 :(得分:10)

它完全取决于资源本身的实现。 try-with-resource语句在close()块中调用finally(并保留异常等)是“只是”语法糖(但非常甜蜜)。

只要流支持close()被调用两次 - 我希望大多数实现都这样做,并且InputStream的契约需要 - 它绝对没问题。

请注意,您熟悉将一种资源包装在另一种资源中,例如,

try (InputStream input = new FileInputStream(...)) {
   try (Reader reader = new InputStreamReader(input, ...)) {
       ...
   }
}

或者使用一个try-with-resources语句:

try (InputStream input = new FileInputStream(...);
     Reader reader = new InputStreamReader(input, ...)) {
   ...
}

在这两种情况下,都会有两个finally块,因此首先调用reader.close(),然后调用input.close() - 但reader.close()无论如何都会关闭input

答案 1 :(得分:6)

Closeable(因此,close())的方法InputStream必须是幂等的:

  

如果流已经关闭,则调用此方法无效。

因此,不止一次关闭InputStream是安全的。

但是,更通用的AutoCloseable接口不要求其close()方法具有幂等性,因此对Closeable以外的资源执行相同操作可能不安全:

  

请注意,与Closeable的close方法不同,此close方法不需要是幂等的。换句话说,不止一次调用此close方法可能会产生一些可见的副作用,这与Closeable.close不同,如果多次调用则需要它无效。但是,强烈建议强制使用此接口的实现者使其接近的方法具有幂等性。

答案 2 :(得分:2)

规范确实说明了一切:如果resource.close()抛出异常,那么异常将从构造中抛出。

当然,规范无法知道任何特定的close方法是否会抛出异常。要找到它,你必须测试你的特定资源。

答案 3 :(得分:0)

您可以尝试在finally语句中关闭它。

InputStream stream = null;
try {
  stream = new InputStream();
  yourMethod(stream);
} catch (...) {

} finally {
  try {
    stream.close()
  } catch (IOException ioe) {
    // can throw IOException while closing closed stream
  }
}