我使用StringReader
将字符串转换为可以上传到SFTP服务器的字符串(它需要一个流)。之后关闭StringReader
是否有任何意义?据我所知,它只是将字符串设置为null
...
我可以这么做,但是因为close方法被标记为抛出一个IOException
并且所有我必须将它包装在try catch中并且代码最终看起来比它可能需要的更加可怕是。
答案 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 具体说明: 在课程阅读器中关闭