我可能对此想法太过思索,但我只是编写了代码:

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++中带有调用其他构造函数的构造函数的常见问题。异常可能导致内存/资源泄漏。

这里有最佳实践吗?

最佳答案



??在您的代码中,它是...并且它当然也将处理资源流的.close()。请参阅下面的更多细节...

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

您在这里还有另一个问题:.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,是的;实际上,除了抛出的异常(IOExceptionException)不同,它仅在“签名明智”方面有所不同。但是行为上有根本的区别。

AutoCloseable.close()的Javadoc(重点是我的):



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



您有两个非常重要的观点:

按照契约(Contract)的
  • Closeable也负责与之相关的所有资源;因此,如果您关闭包裹了BufferedReader和包裹ReaderInputStream,则所有这三个都将关闭;
  • 如果您不止一次调用.close(),就没有进一步的副作用了。

  • 当然,这也意味着您可以选择偏执选项并保留对所有Closeable资源的引用,然后将其全部关闭;但是要当心,如果您有不是AutoCloseableCloseable资源!

    10-06 13:06