我意识到在java中GC最终会清理对象,但是我想问一下不关闭你的字符串编写器是不好的做法,目前我这样做:
private static String processTemplate(final Template template, final Map root) {
StringWriter writer = new StringWriter();
try {
template.process(root, writer);
} catch (TemplateException e) {
logger.error(e.getMessage());
} catch (IOException e) {
logger.error(e.getMessage());
}
finally {
}
return writer.toString();
}
我应该关闭编写器并创建一个像这样的新String:
String result = "";
...
finally {
result = writer.toString();
writer.close();
}
这样做会更好吗?
答案 0 :(得分:67)
答案 1 :(得分:4)
它没有持有任何非内存资源。它将像其他任何东西一样被垃圾收集。 close()probabaly仅存在,因为其他编写器对象确实拥有需要清理的资源,并且需要close()来满足界面。
答案 2 :(得分:2)
不,不关闭StringWriter
不会导致泄密:如上所述,StringWriter#close()
是一个nop,并且编写者只保存内存,而不是外部资源,所以这些将在编写时收集收集。 (显然,它保存对私有字段中不会转义对象的对象的引用,具体为StringBuffer
,因此没有外部引用。)
此外,您通常不应关闭StringWriter
,因为它会为您的代码添加样板,模糊主逻辑,正如我们所见。但是,为了让读者放心,你有意并且故意这样做,我建议评论这个事实:
// Don't need to close StringWriter, since no external resource.
Writer writer = new StringWriter();
// Do something with writer.
如果您确实要关闭作者,最优雅的是使用try-with-resources,当您退出try块的主体时,它会自动调用close()
:
try (Writer writer = new StringWriter()) {
// Do something with writer.
return writer.toString();
}
但是,由于Writer#close()抛出IOException
,您的方法现在还需要抛出IOException
,即使它永远不会发生,或者您需要抓住它,向编译器证明它是被处理的。这非常复杂:
Writer writer = new StringWriter();
try {
// Do something with writer, which may or may not throw IOException.
return writer.toString();
} finally {
try {
writer.close();
} catch (IOException e) {
throw new AssertionError("StringWriter#close() should not throw IOException", e);
}
}
这个级别的样板是必要的,因为你不能只对整个try块进行捕获,否则你可能会意外地吞下代码正文所引发的IOException
。即使目前还没有,也可能会在将来添加一些,并且您希望编译器对此进行警告。 AssertionError
正在记录StringWriter#close()
的当前行为,这可能会在将来的版本中发生变化,尽管这种可能性极小;它还掩盖了在try的主体中可能发生的任何异常(同样,这在实践中永远不会发生)。这是太多的样板和复杂性,你最好省略close()
并评论原因。
一个微妙的问题是,Writer#close()
不仅会IOException
,而且会StringWriter#close()
,因此您无法通过使变量成为{{{{}}来消除异常。 1}}而不是StringWriter
。这是来自String Reader 的不同,它会覆盖Writer
方法并指定它不抛出异常!见my answer至Should I close a StringReader?。这可能看起来不对 - 为什么你会有一个方法什么都不做,但可能会抛出异常? - 但可能是为了向前兼容,留下将来close()
关闭的可能性,因为这通常是作家的问题。 (这也可能只是一个错误。)
总结一下:没有关闭IOException
是没关系的,但不做通常正确的事情的原因,即try-with-resources,只是因为StringWriter
声明了它引发了一个例外,它实际上并没有实际抛出,并且正确处理这个问题是很多样板。在任何其他情况下,最好只使用传统正确的资源管理模式,防止出现问题和头疼。
答案 3 :(得分:0)
在方法结束时,writer
没有任何参考,因此它将被GC释放。