尝试使用资源使用InputStreamReader将流包装在哪里?

2022-05-25 00:00:00 java java-7

我可能想多了,但我只是写了代码:

try (InputStream in = ModelCodeGenerator.class.getClassLoader().getResourceAsStream("/model.java.txt"))
{
    modelTemplate = new SimpleTemplate(CharStreams.toString(new InputStreamReader(in, "ascii")));
}

这意味着InputStreamReader永远不会关闭(但在本例中,我们知道它的Close方法只关闭基础InputStream。)

可以这样写:

try (InputStreamReader reader = new InputStreamReader(...))

但这似乎更糟糕。如果InputStreamReader出于某种原因抛出,InputStream将永远不会关闭,对吗?这是C++中调用其他构造函数的构造函数的常见问题。异常可能导致内存/资源泄漏。

这里有没有最佳实践?


解决方案

这意味着InputStreamReader永远不会关闭

嗯?在您的代码中,它是...它当然也会处理您的资源流的.lose()。有关更多详细信息,请参阅下面的内容...

As @SotiriosDelimanolis mentions但是,您可以在try-with-resource语句的"resource块"中声明多个资源。

您现在有另一个问题:.getResourceAsStream()可以返回NULL;因此您可能有NPE。

如果我是你,我会这么做:

final URL url = ModelCodeGenerator.class.getClassLoader()
    .getResource("/model.java.txt");

if (url == null)
    throw new IOException("resource not found");

try (
    final InputStream in = url.openStream();
    final Reader reader = new InputStreamReader(in, someCharsetOrDecoder);
) {
    // manipulate resources
}

有一个非常重要的问题需要考虑但是...

Closeable确实扩展了AutoCloseable;事实上,它的不同之处只是抛出的异常(IOExceptionvsException)。但行为有根本区别。

来自AutoCloseable.close()的javadoc(重点是我的):

请注意,与Closeable的Close方法不同,此Close方法不要求是幂等的。换句话说,多次调用此Close方法可能会产生一些明显的副作用,这与Closeable.Close不同,Closeable.Close在多次调用时必须无效。但是,强烈建议此接口的实现者使他们的Close方法是幂等的。

确实,Closeable的javadoc对此很清楚:

关闭此流并释放与其关联的所有系统资源。如果流已经关闭,则调用此方法不会产生任何效果。

您有两点非常重要:

  • 根据合同,Closeable还负责与其关联的所有资源;因此,如果关闭包装了InputStreamReaderBufferedReader,则所有这三个资源都将关闭;
  • 如果您多次调用.close(),则不会有进一步的副作用。

当然,这也意味着您可以选择Paranid选项并保留对所有Closeable资源的引用,然后关闭它们;但是,如果您的混合中有AutoCloseable资源而不是Closeable

,请注意

相关文章