释放由 BufferedReader、InputStreamReader 和 InputStream 获取的资源



我有以下一段代码:

public ArrayList<Crime> loadCrimes() throws IOException, JSONException {
ArrayList<Crime> crimes = new ArrayList<Crime>();
BufferedReader reader = null;
try {
// Open and read the file into a StringBuilder
InputStream in = mContext.openFileInput(mFilename);
//what if an exception gets thrown in the line below?
reader = new BufferedReader(new InputStreamReader(in));
StringBuilder jsonString = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
// Line breaks are omitted and irrelevant
jsonString.append(line);
}
// Parse the JSON using JSONTokener
JSONArray array = (JSONArray) new JSONTokener(jsonString.toString()).nextValue();
// Build the array of crimes from JSONObjects
for (int i = 0; i < array.length(); i++) {
crimes.add(new Crime(array.getJSONObject(i)));
}
} catch (FileNotFoundException e) {
// Ignore this one; it happens when starting fresh
} finally {
if (reader != null)
reader.close();
}
return crimes;
}

首先,我想知道为什么我们只对BufferedReader对象调用.close(),而不是对InputStreamInputStreamReader对象调用。我检查了官方的 Oracle 文档,并在 stackoverflow 中浏览了几个问题,根据我所读到的内容,BufferedReader.close()负责释放InputStreamReaderInputStream获得的资源,所以我不必打电话给.close()他们。

这是对的吗?

其次,我想如果在创建InputStream对象之后和创建BufferedReader对象之前抛出异常会发生什么。也就是说,InputStreamReader(InputStream in)构造函数或BufferedReader(Reader in)构造函数引发异常。在这种情况下,我们已经获得了一个文件资源InputStreamBufferedReader对象仍然null,因此在finally块中,不会调用.close()方法,InputStream也不会释放它获得的资源。

然后我阅读了 Oracle 文档,这两个构造函数都没有根据它抛出异常。所以这两行之间不可能出现异常,对吧?

我的最后一个问题是"这段代码是否确保它释放了它获得的所有资源?

首先,我想知道为什么我们只在 BufferedReader 对象上调用 .close(),而不是在 InputStream 和 InputStreamReader 对象上调用。我检查了官方的Oracle文档,并在stackoverflow中浏览了几个问题,根据我所阅读的内容,BufferedReader.close()负责释放InputStreamReader和InputStream获得的资源,所以我不必在它们上调用.close()。 这是对的吗?

是的,它是。

我的最后一个问题是"这段代码是否确保它释放了它获得的所有资源?

最有可能的是,是的。即使在创建InputStreamReaderBufferedReader时发生一些奇怪的异常,在退出定义它们的块后,在GC收集它们之前,它们也会自动关闭。当然,指望 GC 为您清理通常不是一个好主意,所以如果您想 100% 确定,您可能希望在finally块中自己做。

另一种更简单的方法是使用FileReader,它将通过仅使用两个对象来简化代码:

BufferedReader reader = new BufferedReader(new FileReader(fileName));

(我假设您想从文件中读取)。

最新更新