为什么我在finally中关闭流仍会占用资源!
摘要
资深小汪怒斥粗心小吴代码写的不对,小吴表示不服:明明已经在finally代码块中关闭资源了,为什么还要背锅?小吴请各位未来的架构师们帮忙评评理!
public void test() throws IOException {
PrintWriter printWriter = null;
InputStream inputStream = null;
try{
printWriter = new PrintWriter("/test.txt");
inputStream = new InputStream() {
@Override
public int read() throws IOException {
return 0;
}
};
} catch (IOException e) {
e.printStackTrace();
} finally {
inputStream.close();
printWriter.close();
}
}
粗心小吴这次是否能成功甩锅就看各位看官了~
大家评评理
粗心小吴写了这样一段代码,小汪一看你这代码不对啊,流没有正确关闭。
小吴说,怎么可能,我明明已经在finally中关闭流了呀,为什么还说我不正确呢?我不服,上代码,大家评评理!
public void test() throws IOException {
PrintWriter printWriter = null;
InputStream inputStream = null;
try{
printWriter = new PrintWriter("/test.txt");
inputStream = new InputStream() {
@Override
public int read() throws IOException {
return 0;
}
};
} catch (IOException e) {
e.printStackTrace();
} finally {
inputStream.close();
printWriter.close();
}
}
你能看出代码中的异常吗?
问题出在哪里?
问题就是printWriter.close()
并不一定会执行。
瞧一眼inputStream.close()
的代码:
public void close() throws IOException {}
如果inputStream.close()
出现异常,就会直接抛出,这样后面的printWriter.close()
方法就得不到执行,printWriter
的资源就会一直被占用,导致资源浪费。
关闭流的正确方式
资深小汪将finally代码块中关闭流的顺序换了一下,问题迎刃而解。
printWriter.close();
inputStream.close();
为甚么会这样呢?
其实这和两者的close()
方法有关,上源码。
printWriter.close()
的代码实现如下:
public void close() {
try {
synchronized (lock) {
if (out == null)
return;
out.close();
out = null;
}
}
catch (IOException x) {
trouble = true;
}
}
原来printWriter.close()
方法执行异常后并不会抛出异常,而是在catch代码块中处理了,这样即使出现异常,并不会影响到后面inputStream.close()
代码的执行,也就不会影响到inputStream
资源的关闭。