jdk1.7中try-with-resources语法糖详解:主要是针对所有凡是继承了Closeable这个类,系统在方法退出的时候都会自动的关闭资源。
首先回忆一下jdk1.7之前,我们要通过流读取文件时,代码要怎样写?
1.假设本地文件系统d盘下有一个in.txt文件,代码如下:
FileInputStream in = null;
try {
in = new FileInputStream("d:/in.txt");
} catch(Exception e) {
System.out.println(e.getMessage());
throw new RuntimeException("try块中产生了异常",e);
} finally {
if (in != null)
in.close();
}
此时试想一个问题:如果try块中new FileInputStream抛出了异常,在finally块中调用close方法时也抛出了异常,那么最终抛给上层的究竟是哪个异常?
答案是:抛给上层的是close方法产生的异常。
但是很明显,我们希望的是把catch块中捕获的异常进行处理后,继续向上抛出,可结果却因为close方法产生异常而丢失了我们预期的异常。
2.针对此问题,解决方案是:调用in.close()时再次使用try-catch块包裹,代码如下:
FileInputStream in = null;
try {
in = new FileInputStream("d:/in.txt");
} catch(Exception e) {
System.out.println(e.getMessage());
throw new RuntimeException("try块中产生了异常",e);
} finally {
if (in != null)
try {
in.close();
}catch(IOException e) {
e.printStackTrace();
}
}
至此,问题已经得到完美解决。但是,每次处理IO问题时都要编码重复且复杂的代码是不是很繁琐?于是,jdk1.7推出了叫做try-with-resources的语法糖。则上面的代码可以改下如下:
/**
* try-with-resource语法糖
*/
try (FileInputStream in = new FileInputStream("d:/in.txt")) {
// do something
} catch(Exception e) {
System.out.println("message:"+e.getMessage());
throw new RuntimeException("try块中产生了异常",e);
}
3.try()中的类型必须实现AutoCloseable接口(jdk1.7开始引入了此接口,作为Closeable接口的父接口)。
此结构的执行顺序为:
- a.执行try快中语句
- b.调用try()中的所有对象的close()方法
- c.如果try块产生异常,则执行catch中的逻辑
- d.如果存在finally块,则执行其逻辑
另外,还需要注意的是:
如果try块产生了异常,则会忽略close产生的异常(如果真的产生异常的话);否则才会抛出close产生的异常(如果真的产生异常的话)。
因此,try-with-resources语法糖等价于以下写法:
// 此处的try相当于
// try (FileInputStream in = new FileInputStream("d:/in.txt"))
try {
InputStream in = null;
/**
* 以下try-catch可以理解为语法糖自动生成的代码
*/
try {
in = new FileInputStream("d:/in.txt");
// do something
in.close();
} catch (IOException e) {
if (in != null)
try {
in.close();
} catch (IOException ee) {
if (e != ee)
e.addSuppressed(ee);
}
throw e;
}
} catch (IOException e) {
System.out.println(e.getMessage());
throw new RuntimeException("try块中产生了异常", e);
}
总结:到这里大家应该明白了吧,欢迎大家关注并给予评论,我会不断更新新的内容!**