Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 关闭stringwriter不会导致泄漏吗?_Java_Memory Management_Freemarker_Stringwriter - Fatal编程技术网

Java 关闭stringwriter不会导致泄漏吗?

Java 关闭stringwriter不会导致泄漏吗?,java,memory-management,freemarker,stringwriter,Java,Memory Management,Freemarker,Stringwriter,我意识到在java中,GC最终会清理对象,但我想问的是,不关闭字符串编写器是否是一种不好的做法,目前我正在这样做: private static String processTemplate(final Template template, final Map root) { StringWriter writer = new StringWriter(); try { template.process(root, writer);

我意识到在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();
    }
我是否应该关闭writer并创建一个新字符串,如下所示:

String result = "";

...

finally {
  result = writer.toString();
  writer.close();
}
这样做更好吗?

问题非常明确:

关闭StringWriter无效

快速浏览一下就可以确认这一点:

public void close() throws IOException {
}

它没有任何非内存资源。它将像其他任何东西一样被垃圾收集。
close()可能只是因为其他writer对象确实包含需要清理的资源而存在,并且close()是满足接口要求所必需的。

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

否,不关闭
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块主体时,它将自动调用
close()

try (Writer writer = new StringWriter()) {
    // Do something with writer.
    return writer.toString();
}
但是,由于抛出
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()
的当前行为,该行为可能会在未来的版本中发生变化,尽管这是极不可能的;它还屏蔽了try主体中可能发生的任何异常(同样,在实践中永远不会发生这种情况)。这是太多的陈词滥调和复杂性,显然最好省略
close()
并说明原因

一个微妙的点是,
Writer#close()
不仅会抛出一个
IOException
,而且也会抛出一个
IOException
,因此不能通过将变量设为
StringWriter
而消除异常。这与StringReader不同,后者重写
close()
方法并指定它不会引发异常!注意。这看起来可能是错误的-为什么你会有一个方法,它什么都不做,但可能会抛出一个异常??-但可能是为了向前兼容,以便在将来关闭时保留抛出
IOException
的可能性,因为这通常是编写者的问题。(这也可能只是一个错误。)


总而言之:不关闭
StringWriter
是可以的,但不做通常正确的事情的原因,即尝试使用资源,只是因为
close()
声明它会抛出一个实际中不会抛出的异常,而处理这一异常需要大量的模板。在任何其他情况下,最好只使用常规正确的资源管理模式,并防止出现问题和头痛。

另请参见
StringReader
::.
close()
不执行任何操作并引发
IOException
:)它不会引发IOException。它表示它可以抛出异常,但不会。