我正在使用一个BufferedReader包装FileReader读取一个本地文件:
BufferedReader reader = new BufferedReader(new FileReader(fileName));
// read the file
// (error handling snipped)
reader.close();
我是否需要关闭()FileReader,或者包装器将处理它?
我曾见过这样的代码:
FileReader fReader = new FileReader(fileName);
BufferedReader bReader = new BufferedReader(fReader);
// read the file
// (error handling snipped)
bReader.close();
fReader.close();
这个方法是从servlet调用的,我希望确保没有留下任何句柄。
您不需要关闭被包装的读取器/写入器。
如果你已经看过文档(Reader.close(),Writer.close()),你会看到在Reader.close()中它说:
关闭流并释放与之关联的所有系统资源。
它只是说它“释放与之相关的任何系统资源”。即使它没有证实…它会促使你开始深入研究。如果你去Writer.close(),它只声明它关闭自己。
在这种情况下,我们会参考OpenJDK来查看源代码。
在BufferedWriter第265行,你会看到out.close()。所以它没有关闭自己。是别的东西。如果你在类中搜索“out”的出现,你会注意到在构造函数的第87行,out是写入器,类包装它调用另一个构造函数,然后将out形参分配给它自己的out变量。
所以. .其他人呢?你可以在BufferedReader第514行、BufferedInputStream第468行和InputStreamReader第199行看到类似的代码。其他我不知道,但这应该足以假设他们做。
在您的场景中,只需要关闭BufferedReader。
正如其他人指出的那样,JavaDocs是模棱两可的。当你想要立即调用close时,使用try-with-resources块是最好的方法,但如果你需要保持读取器打开,它就不起作用了(例如,一个类有一个方法,返回一个使用底层读取器的流——调用close通常是调用方的责任)。
如果您无法访问源代码,并且希望查看您的阅读器和JVM调用在您的情况下是否关闭各种阅读器和流,那么可以将close方法重写为一个简单的测试。
Path path = Paths.get("/home/example/test.txt");
InputStream fileInputStream = new FileInputStream(path.toFile()) {
public void close() throws IOException {
System.out.println("FileInputStream::close()");
super.close();
}
};
Reader inputStreamReader = new InputStreamReader(fileInputStream, Charsets.UTF_8) {
public void close() throws IOException {
System.out.println("InputStreamReader::close()");
super.close();
}
};
BufferedReader bufferedReader = new BufferedReader(inputStreamReader) {
public void close() throws IOException {
System.out.println("BufferedReader::close()");
super.close();
}
};
bufferedReader.close();
当你运行上面的程序时,你会看到类似的结果:
BufferedReader::close()
InputStreamReader::close()
FileInputStream::close()
由于JavaDoc中没有编写明确的规范,我们无法确定所有jvm的行为。然而,大多数阅读器/流似乎都遵循上述模式(例如,你可以在上面的例子中添加一个GZIPInputStream,并看到GZIPInputStream::close()也会被调用)。