我应该关闭StringReader吗



我使用StringReader将字符串转换为可以上传到SFTP服务器的内容(它需要一个流)。之后关闭StringReader有什么意义吗?据我在源代码中所见,它只是将字符串设置为null。。。

我可以这么做,但由于close方法被标记为抛出一个IOException,我所要做的就是用try-catch来包装它,而代码最终看起来比它可能需要的要可怕得多。

如果你知道你要处理的是一个将要丢弃的StringReader,我看不出有任何理由关闭它。我无法想象在关闭它之后,有什么原因会保留对它的引用,所以将字符串设置为null进行垃圾收集并没有真正的好处。如果您正在创建一个使用Reader的方法,那么关闭它可能是有意义的,因为您不知道底层类型。

它的作用不止于此。如果我可以引用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(。然而,Reader.close()确实如此。所以您已经允许Reader的其他实现,所以您必须关闭它,因为您不知道最终会得到什么Reader实现。如果我们谈论的是从未离开该范围的三行代码,那么声明变量StringReader并无论如何调用close(在这种情况下,没有异常处理)。

尽管严格来说不是必要的,因为StringReader只保存一个字符串,但作为一种良好的形式,关闭所有读卡器总是一个好主意。今天,您的代码可能使用StringReader,但如果您将其更改为另一个真正需要关闭的Reader,则您的代码w/out关闭将是错误的,而您的w/close则可以。

如果变量的类型为StringReader而不是Reader,则不需要捕获异常,因为StringReader#close()不会抛出异常:只有Reader#close()会抛出异常。因此,您可以使用try-with-resources自动关闭阅读器,而无需使用样板文件来处理不会发生的异常。Reader#close()抛出IOException意味着子类型可以抛出这种类型的异常,而不是它们必须。这是一种罕见的情况,您希望用子类型而不是超类型来声明变量;请参阅在java中使用接口或类型进行变量定义?了解更多信息。

因此,我建议如下,它只需要一个级别的嵌套,这与资源相当:

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

然而,关闭StringReader没有什么价值,因为它不包含外部资源(比如说,只有Java托管内存,而不是文件句柄或本机内存),所以省略它是可以的,尽管我建议注释说明为什么这是安全的,因为否则不关闭读卡器是令人惊讶的。正如您所注意到的,close()只是清空了字段,根据JDK8的源代码:StringReader.java:198。如果你想避免嵌套和关闭,你可以写这样的:

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

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

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

正常的资源尝试在这里起作用,因为StringReader#close()覆盖Reader#close(),并幸运地声明它不抛出IOException

请注意,这不是字符串Writer的情况:StringWriter#close()确实声明它抛出IOException,尽管它是nop!这可能是为了前向兼容性,所以它可能会在未来的实现中引发异常,尽管这不太可能。查看我对的回答不关闭字符串写入程序会导致泄漏吗?。

在这种情况下(如果方法没有抛出异常,但接口声明它可以),写这篇文章的最简单方法是:

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(比如说,作为工厂的返回类型),那么您需要关闭它并处理可能的异常,因为您不知道它可能包含什么资源,它可能会抛出异常。

如果关闭流并释放与之相关的任何系统资源。一旦关闭流,进一步的read()、ready()、mark()或reset()调用将引发IOException。关闭以前关闭的流没有任何效果。指定人:关闭接口关闭指定人:关闭类阅读器

相关内容

  • 没有找到相关文章

最新更新