我应该关闭StringReader吗?

时间:2011-05-25 09:08:35

标签: java stringreader

我使用StringReader将字符串转换为可以上传到SFTP服务器的字符串(它需要一个流)。之后关闭StringReader是否有任何意义?据我所知,它只是将字符串设置为null ...

我可以这么做,但是因为close方法被标记为抛出一个IOException并且所有我必须将它包装在try catch中并且代码最终看起来比它可能需要的更加可怕是。

5 个答案:

答案 0 :(得分:13)

如果你知道你正在处理你将要扔掉的StringReader,我认为没有理由关闭它。在你关闭它之后我无法想象你有什么理由持有它的引用,因此对于垃圾收集设置为null的字符串没有任何实际好处。如果您创建的方法需要Reader,那么关闭它可能是有意义的,因为您不知道基础类型。

答案 1 :(得分:4)

虽然严格来说没有必要,但因为StringReader只保留一个String,所以无论如何最好关闭所有的Readers。今天你的代码可能正在使用StringReader,但是如果你把它改成了另一个真正需要关闭的Reader,你的代码没有结束将是错误的,而你的w / close会很好。

答案 2 :(得分:3)

它不止于此。如果我引用JavaDoc:

/**
 * Closes the stream and releases any system resources associated with
 * it. Once the stream has been closed, further read(),
 * ready(), mark(), or reset() invocations will throw an IOException.
 * Closing a previously closed stream has no effect.
 */

所以是的,你应该关闭那个读者。不是为了资源,而是为了好风格和程序员可能会跟随你。您不知道此实例将传递到何处以及其他人将尝试使用它做什么。有一天,您可能还会选择更改界面并接受任何Reader实现,在这种情况下,您可能会处理需要调用close()来释放资源的Reader。

因此,一旦完成此实例,防止进一步(可能错误)使用它是一种很好的方式。而且由于它没有受到伤害,它只能防止将来出现可能的错误。

修改 既然你说,你的close()方法声明了一个异常它可能会抛出我会说你需要来调用close(),因为StringReader.close()不会抛出异常。但是,Reader.close()可以。因此,您已经允许其他Reader实现,因此您必须关闭它,因为您无法知道最终将获得哪些Reader实现。如果我们讨论的是从不离开该范围的三行代码,请声明您的变量StringReader并且无论如何都要调用close(在这种情况下没有异常处理)。

答案 3 :(得分:0)

如果变量的类型为StringReader,而不是Reader,则不需要捕获异常,因为StringReader#close()不会引发异常:只有Reader#close()。因此,您可以使用try-with-resources自动关闭阅读器,而无需使用样板来处理不会发生的异常。 Reader#close()投掷IOException意味着的子类型可以抛出此类异常,而不是必须。这是您想要使用子类型而不是超类型声明变量的罕见情况之一;有关详情,请参阅Use interface or type for variable definition in java?

因此,我建议以下内容,只需要一个级别的嵌套,这对于资源来说是相同的:

try (StringReader reader = new StringReader(string)) {
    // Do something with reader.
}

但是,关闭StringReader几乎没有价值,因为它不包含外部资源(只有Java管理的内存,而不是文件句柄或本机内存,所以)可以省略它虽然我推荐一条评论说明为什么这是安全的,因为否则不会关闭读者是令人惊讶的。如您所知,根据JDK 8源close()// Don't need to close StringReader, since no external resource. StringReader reader = new StringReader(string); // Do something with reader. 只会使该字段为空:StringReader.java:198。如果你想避免嵌套和关闭,你可以写下这个:

// Don't need to close StringReader, since no external resource.
Reader reader = new StringReader(string);
// Do something with reader.

...或(使用更通用的变量类型):

StringReader#close()

正常的try-with-resources在这里工作,因为Reader#close()会覆盖IOException,并且仁慈地声明它不会抛出IOException

请注意, 的情况 ,尽管是一个小鸟!这可能是为了向前兼容,因此它可能会在未来的实现中引发异常,尽管这不太可能。见StringWriter#close()my answer

在这种情况下(如果方法没有抛出异常,但界面声明它可以),那么你可能提到的写这个的紧密方法是:

Reader reader = new StringReader(string);
try {
    // Do something with reader, which may or may not throw IOException.
} finally {
    try {
        reader.close();
    } catch (IOException e) {
        throw new AssertionError("StringReader#close() cannot throw IOException", e);
    }
}

这个级别的样板是必要的,因为你不能只在整个try块上设置一个catch,否则你可能会意外地吞下代码体所抛出的IOException。即使目前没有,也可能会在未来添加一些,并且您希望编译器对此进行警告。另请注意,记录当前行为的AssertionError也会掩盖try语句正文引发的异常,但这绝不会发生。如果这是另一种选择,那么你最好省略close()并评论原因。

这个答案取决于你自己创建StringReader的事实;当然,如果你从其他地方收到Reader(比如工厂的返回类型),那么你需要关闭它并处理可能的异常,因为你不知道它可能拥有什么资源,它可能会抛出异常。

答案 4 :(得分:-1)

如果您关闭流并释放与其关联的任何系统资源。关闭流后,进一步的read(),ready(),mark()或reset()调用将抛出IOException。关闭先前关闭的流无效。 具体说明: 关闭接口Closeable 具体说明: 在课程阅读器中关闭