6

假设我正在使用一个文档记录不佳的第三方库,它没有可用的源代码。库的方法之一接受InputStream加载各种数据。

由于缺乏文档,尚不清楚该方法是否在完成后关闭流,因此一种可能的解决方案可能是将调用包装在 try-with-resource 中,只是为了安全起见。

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

4

4 回答 4

10

这将完全取决于资源本身的实现。close()try-with-resource 语句是用于在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

于 2014-01-21T09:54:20.940 回答
6

(因此, of close())的方法必须是幂等的:CloseableInputStream

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

因此,InputStream多次关闭是安全的。

但是,更通用AutoCloseable的接口不需要它的close()方法是幂等的,因此对其他资源执行相同操作可能是不安全的Closeable

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

于 2014-01-21T09:56:31.260 回答
2

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

当然,规范无法知道任何特定close方法是否会引发异常。要找出这一点,您必须测试您的特定资源。

于 2014-01-21T09:55:09.207 回答
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
  }
}
于 2014-01-21T09:55:33.393 回答