JAVA将字符串导致,关于java:不会关闭一个字符串写入器导致泄漏?

我意识到,在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();

}

这样做更好吗?

另请参见StringReader的相应问题:我应该关闭StringReader吗?.

JavaDoc非常明确:

Closing a StringWriter has no effect.

快速查看代码就可以确认:

public void close() throws IOException {

}

什么都不做,扔了IOException的close()。

它没有任何非内存资源。它将像其他任何东西一样被垃圾收集。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);

}

}

这一级别的样板文件是必要的,因为您不能将catch放在整个try块上,否则您可能会意外地吞下代码体抛出的IOException。即使当前没有,将来也可能会添加一些,编译器会警告您这一点。AssertionError正在记录StringWriter#close()的当前行为,该行为可能在将来的版本中发生变化,尽管这是极不可能的;它也掩盖了在尝试体中可能发生的任何异常(同样,这在实践中不应该发生)。这是太多的样板文件和复杂性,显然您最好省略close()并评论原因。

一个微妙的点是,不仅Writer#close()抛出了IOException,StringWriter#close()也抛出了IOException,所以不能通过将变量设置为StringWriter而不是writer来消除异常。这与StringReader不同,它重写close()方法并指定不引发异常!看到我的答案了,我应该关闭一个字符串阅读器吗?。这可能看起来是错误的–为什么您会有一个方法,它只会抛出异常??—但这可能是为了向前兼容,为以后在关闭时抛出一个IOException留出了可能性,因为这通常是作者面临的问题。(这也可能是一个错误。)

总而言之:不关闭一个StringWriter是可以的,但是不做通常正确的事情的原因,即尝试使用资源,仅仅是因为close()声明它抛出了一个异常,实际上它并没有抛出,而处理这个异常则是一个很大的样板。在任何其他情况下,最好只是使用传统的正确的资源管理模式,防止问题和头疼。

在方法的末尾,没有对writer的引用,因此GC将释放它。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值