在使用必须关闭的资源时,try-catch-finally是非常常用的选择,但是JDK7发布后,可以改变这种现状。
1. try-with-resources的使用
java中非常多的资源都继承了Closeable,例如FileInputStream了。在JDK1.7之后,继承了该接口的资源可以采取try-with-resources的方式关闭资源,因为该接口中有一个close方法,try-with-resources中的资源使用完毕后,close方法会被自动调用,安全的关闭资源。如下是try-with-resources和try-catch-finally的使用方式。
/* jdk7之前*/
public class ClassTest{
private static final String FileName = "file.txt";
public void dosomething() throws IOException {
FileInputStream in = null;
try {
in= new FileInputStream(FileName);
char c1 = (char) in.read();
System.out.println("c1=" + c1);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in!= null) {
in.close();
}
}
}
}
/* jdk7之后*/
public class ClassTest{
private static final String FileName = "file.txt";
public void dosomething() throws IOException {
FileInputStream in = null;
try(FileInputStream in = new FileInputStream(FileName)){
char c1 = (char) in.read();
System.out.println("c1=" + c1);
} catch (IOException e) {
e.printStackTrace();
}
}
}
try-with-resources使用后,不需要再调用手动调用close方法,代码也省去了finally块的编写,看上去非常整洁。尤其是try-catch-finally多次嵌套时,更能体现try-with-resources代码的整洁。
2. Closeable接口的使用
设计一个资源类,继承Closeable接口。
public class ClassTest implements Closeable{
public void doSomething() throws Exception{
System.out.println("使用资源");
}
@Override
public void close() throws Exception {
System.out.println("资源关闭");
}
public static void main(String[] args){
try(ClassTest ct = new Closeable()){
ct.doSomething();
}catch (Exception e) {
e.printStackTrace();
}
}
}
执行上述代码打印如下:
使用资源
资源关闭
3. finally的异常屏蔽问题
在第1点中,JDK7之前try-catch-finally的使用中,若第八行in.read();代码异常,则程序会在第十一行 执行e.printStackTrace();代码抛出异常,再进入到finally代码中,调用in.close()关闭输入流。但是如果这个时候in.close()代码异常,会在抛出一个异常,但是该异常会屏蔽第一次抛出的异常,使得开发人员只能看到第二次抛出的异常,这对以开发人员的调试工作非常不友好。但是如果使用的是try-with-resources,则两个异常都会被抛出来,并且被屏蔽的异常会用Suppressed来标注。(但是我在JDK1.8中尝试这样做,希望看到finally屏蔽第一次异常的效果,但事实是,并没有异常被屏蔽,不知道是不是JDK1.8修复了这个问题。)