我使用 aStringReader
将字符串转换为可以上传到 SFTP 服务器的内容(它需要一个流)。之后关闭它有什么意义StringReader
吗?据我在源代码中看到的,它只是将字符串设置为null
...
我可以这样做,但是由于 close 方法被标记为抛出 anIOException
并且我必须将它包装在 try catch 中,并且代码最终看起来比它可能需要的要可怕得多。
我使用 aStringReader
将字符串转换为可以上传到 SFTP 服务器的内容(它需要一个流)。之后关闭它有什么意义StringReader
吗?据我在源代码中看到的,它只是将字符串设置为null
...
我可以这样做,但是由于 close 方法被标记为抛出 anIOException
并且我必须将它包装在 try catch 中,并且代码最终看起来比它可能需要的要可怕得多。
如果你知道你正在处理一个StringReader
你会扔掉的东西,我看不出有任何理由关闭它。我无法想象在关闭它之后你会持有对它的引用的任何原因,因此设置null
为垃圾收集的字符串没有真正的好处。如果您正在创建一个采用 a 的方法,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() 因为 StringReader.close() 不会抛出异常。但是, Reader.close() 可以。因此,您已经允许 Reader 的其他实现,因此您必须关闭它,因为您不知道最终会获得哪些 Reader 实现。如果我们正在谈论永远不会离开该范围的三行代码,请声明您的变量 StringReader 并调用 close (在这种情况下不进行异常处理)。
虽然严格来说没有必要,因为 StringReader 只保留一个字符串,作为一种良好的形式,无论如何关闭所有阅读器总是一个好主意。今天,您的代码可能正在使用 StringReader,但如果您将其更改为另一个确实需要关闭的 Reader,则您的代码没有关闭将是错误的,而您的 w/ 关闭会很好。
如果您的变量具有 type StringReader
,而不是 ,则不需要捕获异常Reader
,因为StringReader#close()
不会引发异常:只会Reader#close()
。因此,您可以使用try-with-resources自动关闭阅读器,而无需使用样板来处理不会发生的异常。Reader#close()
throwingIOException
意味着子类型可以抛出这种类型的异常,而不是它们必须。这是您要声明具有子类型而不是超类型的变量的罕见情况之一;请参阅在 java 中使用接口或类型进行变量定义?更多。
因此,我建议以下内容,它只需要一层嵌套,这对于资源来说是同等的:
try (StringReader reader = new StringReader(string)) {
// Do something with reader.
}
但是,关闭 a 没有什么价值StringReader
,因为它不包含外部资源(例如,只有 Java 管理的内存,而不是文件句柄或本机内存),所以可以省略它,尽管我建议您发表评论说明为什么这是安全的,因为否则不关闭读者是令人惊讶的。正如您所注意到close()
的,根据 JDK 8 来源,只需将该字段清空: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.
正常的 try-with-resources 在这里有效,因为它StringReader#close()
会覆盖Reader#close()
并仁慈地声明它不会 throw IOException
。
请注意,String Writer并非如此:确实声明它 throws ,尽管它是一个 nop!这大概是为了向前兼容,所以它可能会在未来的实现中抛出异常,尽管这不太可能。请参阅我对
不会关闭 stringwriter 导致泄漏的回答?.StringWriter#close()
IOException
在这种情况下(如果该方法没有抛出异常,但接口声明它可以),编写这个的紧凑方法,你大概是在暗示,是:
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
从其他地方收到 a (例如作为工厂的返回类型),那么您需要关闭它并处理可能的异常,因为您不知道它可能拥有什么资源,并且它可能会抛出一个例外。
如果您关闭流并释放与之关联的任何系统资源。关闭流后,进一步的 read()、ready()、mark() 或 reset() 调用将引发 IOException。关闭以前关闭的流没有效果。指定者:Closeable接口中的close指定者:类Reader中的close