我有以下代码:
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;
}
首先,我想知道为什么我们只在.close()
对象上调用BufferedReader
,而不是在InputStream
和InputStreamReader
对象上调用BufferedReader.close()
。我检查了官方的Oracle文档并浏览了stackoverflow中的几个问题,根据我读过的InputStreamReader
负责发布InputStream
和.close()
获取的资源,所以我不必在它们上面调用InputStream
。
这是对的吗?
其次,我想如果在创建BufferedReader
对象之后和创建InputStreamReader(InputStream in)
对象之前抛出异常会发生什么。也就是说,BufferedReader(Reader in)
构造函数或InputStream
构造函数抛出异常。在这种情况下,我们已经获得了BufferedReader
的文件资源,但null
对象仍为finally
,因此在.close()
块中,InputStream
方法不会被调用,{{1}}不会释放它已获得的资源。
然后我阅读了Oracle文档,这两个构造函数都没有根据它抛出异常。所以这两行之间不可能发生异常,对吧?
我的最后一个问题是“这段代码是否确保它释放了它所获得的所有资源?”
答案 0 :(得分:1)
首先,我想知道为什么我们只在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));
(我假设你想从文件中读取)。