我是否需要关闭java.io包的读卡器装饰器?

我是否需要关闭java.io包的读卡器装饰器?,java,io,Java,Io,我需要解析一个对象,我需要将接收到的读取器包装到一个PushbackReader中。我是否需要在任何情况下关闭PushbackReader,或者由于我没有打开的是底层读取器,所以让它保持打开状态是否足够安全 与 或者只写以下内容是否足够安全: public static MyObject parse(Reader reader) throws IOException, ParseException { return parseMyObject(new PushbackReader(reade

我需要解析一个对象,我需要将接收到的读取器包装到一个PushbackReader中。我是否需要在任何情况下关闭PushbackReader,或者由于我没有打开的是底层读取器,所以让它保持打开状态是否足够安全

或者只写以下内容是否足够安全:

public static MyObject parse(Reader reader) throws IOException, ParseException {
  return parseMyObject(new PushbackReader(reader, PUSHBACK_SIZE));
}
以下是我如何调用解析器的信息:

BufferedReader reader = new BufferedReader(...);
try {
  while (...) {
    list.add(MyObjectParser.parse(reader));
  }
} catch (IOException e) {
  throw new RuntimeException("Could not read the stream", e);
} catch (ParseException e) {
  throw new ParseRuntimeException("Could not parse the stream", e);
} finally {
  // No need for null check.
  reader.close();
}
如果被调用方将关闭底层读取器,则不需要在PushbackReader上调用close。PushbaseReader只是一个带有缓冲区的包装器,当您使用它时,缓冲区将被垃圾收集。对其调用close将关闭底层读取器,如果希望该方法关闭它,则希望保留该读取器

更新:根据您的代码,您似乎无法在PushbackReader上调用close,因为它还将关闭您的底层读取器。下一次迭代应该会失败,如果您这样做,那么流将被关闭,我可以看到一个异常。例如,此示例失败:

BufferedReader reader = new BufferedReader(new StringReader("foo"));
new PushbackReader(reader).close();
reader.read(); // IOException: Stream closed

最好的做法是始终关闭读卡器-如果它们恰好是其他读卡器的包装器,那么它们应该将关闭操作级联到它们

在您的代码片段中,这只是决定责任所在的问题。应该有人关闭阅读器,可以是parse方法,也可以是parseMyObject方法。我更喜欢parse方法,因为这样代码更具可读性——创建/打开读卡器的方法就是关闭读卡器的方法。 否则,您会遇到奇怪的情况—其他人可能会使用parseMyObject,然后突然惊讶于它关闭了reader参数

更新:


现在我看到了您的问题的更新,这归结为在循环中接受一个reader参数,然后多次包装它。我建议您重构代码,以便只使用PushbackReader包装一次。或者将读卡器的初始化代码移到内部方法中。

如果您记住了几个关键点,就不会太复杂了:

可以多次关闭流/读/写器。第二次或随后的收盘无效。 流包装器PushBackReader、BufferedReader等在包装器关闭时关闭底层流。 垃圾收集器通常不会自动关闭流,除非流拥有OS上的资源文件描述符、套接字等。 通常,流的创建者将使用try finally块在完成流时关闭流,例如。 因此,作为一般规则,除非有充分的理由关闭读取器,否则解析不应关闭读取器,例如,IOException使流处于不确定状态,以防调用方希望将流用于其他用途


如果parse在流结束时关闭它,这可能不是世界末日,但是如果它关闭了,那么您应该明确地记录这一事实。

Mmm。。。有人能确认GC将有效地关闭我的底层阅读器吗?我不明白为什么会发生这种事,这绝对是我不想要的行为。我更新了答案以澄清。您确实需要从被调用方或此方法内部关闭基础读取器。看起来您不需要关闭PushbackReader。事实上,关闭它不是一个问题吗?这将关闭底层流,并在下一次迭代中触发IOException。请参阅我的更新问题,了解它通常是如何使用的。我的主要目标是谁打开它,谁关闭它。我想我们在主要观点上是一致的,我误解了你最初的问题parseMyObject需要一个推送阅读器,还是只需要一个普通的阅读器。如果parse只是获取一个普通的读取器,那么pushback读取器没有效果,因为我没有打开它的底层读取器????
BufferedReader reader = new BufferedReader(new StringReader("foo"));
new PushbackReader(reader).close();
reader.read(); // IOException: Stream closed
Reader reader = new FileReader(file);
try {
    parse(reader);
} finally {
    reader.close();
}