不会关闭字符串打字机会导致泄漏?

我意识到,在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 result = "";

...

finally {
  result = writer.toString();
  writer.close();
}

这更好吗?


javadoc非常明确:

关闭StringWriter不起作用。

快速浏览代码证实了这一点:

public void close() throws IOException {
}

它不包含任何非内存资源。 它将像其他任何垃圾一样被收集起来。 close()可能性仅仅存在,因为其他作者对象确实需要清理资源,并且需要close()来满足接口。


不,不关闭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块上放一个catch,否则可能会意外地吞下代码主体抛出的IOException 。 即使目前还没有,有些可能会在未来添加,您希望编译器提醒您。 AssertionError记录了StringWriter#close()的当前行为,该行为在未来的版本中可能会发生变化,尽管这是不太可能的; 它也掩盖了尝试主体中可能发生的任何异常(同样,这在实践中绝不会发生)。 这是太多的样板和复杂性,你最好省略close()和评论原因。

微妙的一点是, Writer#close()不仅会抛出IOException ,而且StringWriter#close()也会抛出异常,因此您无法通过将该变量设置为StringWriter而不是Writer来消除该异常。 这与StringReader不同,它重写close()方法并指定它不会抛出异常! 查看我的答案我应该关闭一个StringReader吗? 这可能看起来错了 - 为什么你会有一个什么都不做,但可能会抛出异常的方法? - 但大概是为了向前兼容,在将来会留下抛出IOException的可能性,因为这对于作者来说通常是个问题。 (这也可能只是一个错误。)

总结一下:不关闭StringWriter ,但是不做正常事情的原因,就是try-with-resources,只是因为close()声明抛出了一个实际上并没有抛出的异常,并且正确地处理这是很多样板。 在任何其他情况下,最好只使用传统上正确的资源管理模式,并防止出现问题和头疼。

链接地址: http://www.djcxy.com/p/82463.html

上一篇: Will not closing a stringwriter cause a leak?

下一篇: Overflow for background color of text