我可能对此想法太过思索,但我只是编写了代码:
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
,是的;实际上,除了抛出的异常(IOException
与Exception
)不同,它仅在“签名明智”方面有所不同。但是行为上有根本的区别。从
AutoCloseable
的.close()
的Javadoc(重点是我的):确实,
Closeable
的javadoc对此很清楚:您有两个非常重要的观点:
按照契约(Contract)的
Closeable
也负责与之相关的所有资源;因此,如果您关闭包裹了BufferedReader
和包裹Reader
的InputStream
,则所有这三个都将关闭; .close()
,就没有进一步的副作用了。 当然,这也意味着您可以选择偏执选项并保留对所有
Closeable
资源的引用,然后将其全部关闭;但是要当心,如果您有不是AutoCloseable
的Closeable
资源!