在进行IO操作的时候,不可避免的要进行异常捕获和处理。有些朋友比较懒,或者说对于自己的代码非常自信,直接将异常一股脑的throws出去。这样的代码看着整洁舒服,容易理解,但是一旦出现异常就比较麻烦了。
比如一个简单的展示文本文件内容的方法,有些人喜欢这样写:
static void showAll(String pathname) throws IOException{
File file = new File(pathname);
FileInputStream fis = new FileInputStream(file);
byte[] all = new byte[(int)file.length()];
fis.read(all);
for(byte b : all){
System.out.print((char)b);
}
fis.close();
}
这样写有毛病吗?咋一看没什么毛病啊,我们分析一下,在方法正常执行没有出现异常的情况下,这样的写法确实是正确的。那要是程序没有成功读取到文件怎么办,程序肯定会出现异常,程序在执行到异常的代码时就是直接抛出异常并直接结束了该方法。这有什么问题吗?有问题,问题就在于后面的fis.close();没有执行到,这里就出现了文件输入流开了没有进行关闭。如果流没有关闭的话,gc很难对其进行回收,如果多次出现这样的情况,无效的内存消耗会越来越大。而且通常的情况时我们要对异常进行相关的处理。
那么我们就换try捕获异常试试,这样会不会有什么讲究呢。
static void showAll(String pathname){
try {
File file = new File(pathname);
FileInputStream fis = new FileInputStream(file);
byte[] all = new byte[(int)file.length()];
fis.read(all);
for(byte b : all){
System.out.print((char)b);
}
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
我们一起分析一下,其实这种写法和只在在方法后面throws异常无异,而且还看起来没有那样好看。我在前面分析try-catch里面finally的时候已经研究过了,try里面如果出现异常,异常后面的代码就不会再被执行,程序而是跳转到catch里面去执行代码了。由此我们可以将fis.close();这段代码在catch里面也写一遍,这样无论程序是否出现异常都能让流正常关闭。
static void showAll(String pathname){
FileInputStream fis = null;
try {
File file = new File(pathname);
fis = new FileInputStream(file);
byte[] all = new byte[(int)file.length()];
fis.read(all);
for(byte b : all){
System.out.print((char)b);
}
fis.close();
} catch (IOException e) {
try {
fis.close();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
但是这样会发现fis.close();这个明明只需要写一遍的代码,我们却写了两边,而且只可能有一个会被执行到。既然我们之前分析了finally的作用,那么我们就可以将流的关闭放在finally里面。
static void showAll(String pathname){
FileInputStream fis = null;
try {
File file = new File(pathname);
fis = new FileInputStream(file);
byte[] all = new byte[(int)file.length()];
fis.read(all);
for(byte b : all){
System.out.print((char)b);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
这里就体现了finally的作用,无论程序走没走到catch里面,最终都是要过finally里面的,所以,我们在finally里面处理流的关闭操作是最恰当的。
那么对所讲的做一下总结:1、在处理IO操作时最好使用try-catch对流等相关的异常进行捕获以及异常处理;2、对流的关闭操作尽量放在finally里面进行,这样的代码看起来更清晰更舒服,也更安全。
如有更多需要了解或者交流的内容可在评论区进行留言或者关注我的个人微信公众号进行讨论。