我有以下一段代码:
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()
,而不是对InputStream
和InputStreamReader
对象调用。我检查了官方的 Oracle 文档,并在 stackoverflow 中浏览了几个问题,根据我所读到的内容,BufferedReader.close()
负责释放InputStreamReader
和InputStream
获得的资源,所以我不必打电话给.close()
他们。
这是对的吗?
其次,我想如果在创建InputStream
对象之后和创建BufferedReader
对象之前抛出异常会发生什么。也就是说,InputStreamReader(InputStream in)
构造函数或BufferedReader(Reader in)
构造函数引发异常。在这种情况下,我们已经获得了一个文件资源InputStream
但BufferedReader
对象仍然null
,因此在finally
块中,不会调用.close()
方法,InputStream
也不会释放它获得的资源。
然后我阅读了 Oracle 文档,这两个构造函数都没有根据它抛出异常。所以这两行之间不可能出现异常,对吧?
我的最后一个问题是"这段代码是否确保它释放了它获得的所有资源?
首先,我想知道为什么我们只在 BufferedReader 对象上调用 .close(),而不是在 InputStream 和 InputStreamReader 对象上调用。我检查了官方的Oracle文档,并在stackoverflow中浏览了几个问题,根据我所阅读的内容,BufferedReader.close()负责释放InputStreamReader和InputStream获得的资源,所以我不必在它们上调用.close()。 这是对的吗?
是的,它是。
我的最后一个问题是"这段代码是否确保它释放了它获得的所有资源?
最有可能的是,是的。即使在创建InputStreamReader
或BufferedReader
时发生一些奇怪的异常,在退出定义它们的块后,在GC收集它们之前,它们也会自动关闭。当然,指望 GC 为您清理通常不是一个好主意,所以如果您想 100% 确定,您可能希望在finally
块中自己做。
另一种更简单的方法是使用FileReader
,它将通过仅使用两个对象来简化代码:
BufferedReader reader = new BufferedReader(new FileReader(fileName));
(我假设您想从文件中读取)。