相信大多数人在使用Java的时候,经常会使用到try-finally去关闭各种打开的资源,比如数据库连接,文件流等。于是,我们的代码经常就会像这个样子:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadFile {
public static void main(String[] args) {
BufferedReader reader = null;
String buffer = null;
try {
reader = new BufferedReader(new FileReader("src/testRead.txt"));
do {
buffer = reader.readLine();
System.out.println(buffer);
} while (reader.read() != -1);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
一个简单的Java获取文件读取操作。可是代码却冗长的像老太婆的裹脚布又长又臭:我们在finally中为了防止关闭reader的时候发生异常,不得不再加一层的try-catch操作来进行异常捕获。
还有一个更大的问题是,假如在buffer = reader.readLine()这句语句抛出了异常,而同时,在finally中的reader.close()语句也发生了异常,那么finally块中的异常信息就会覆盖掉reader.readLine()语句的异常信息。也就是说异常堆栈跟踪中没有第一个异常的记录,这可能会使实际系统中的调试变得非常复杂。虽然可以通过编写代码来抑制第二个异常而支持第一个异常,但是这会使得编写的人员异常痛苦,而且代码也会越来越长。
那么怎么解决这样的问题呢?让人高兴的是,在Java7中引入了try-with-resources语句,就是用来处理这个问题的,我们看看用try-with-resources后的代码:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadFile {
public static void main(String[] args) {
String bufferSugar = null;
try (BufferedReader readerSugar = new BufferedReader(new FileReader("src/testRead.txt"))) {
bufferSugar = readerSugar.readLine();
System.out.println(bufferSugar);
} catch (IOException e) {
e.printStackTrace();
}
}
}
是不是简单了很多,主要的代码都用来处理业务逻辑而没有去过多的关心资源的关闭。而且,如果异常是由 readLine 调用和不可见的 close 抛出的,则后一个异常将被抑制,以支持前一个异常。实际上,还可能会抑制多个异常,以保留实际希望看到的异常。这些被抑制的异常不会仅仅被抛弃;它们会被打印在堆栈跟踪中,并标记它们被抑制。可以通过编程方式使用 getSuppressed 方法访问到它们。
那么try-with-resources做了什么让我们不再需要自己手动调用资源的close呢?用jad工具反编译看看源码:import java.io.*;
public class ReadFile
{
public ReadFile(){}
public static void main(String args[])
{
String bufferSugar = null;
Exception exception;
exception = null;
Object obj = null;
BufferedReader readerSugar = new BufferedReader(new FileReader("src/testRead.txt"));
bufferSugar = readerSugar.readLine();
System.out.println(bufferSugar);
if(readerSugar != null)
readerSugar.close();
break MISSING_BLOCK_LABEL_90;
exception;
if(readerSugar != null)
readerSugar.close();
throw exception;
Exception exception1;
exception1;
if(exception == null)
exception = exception1;
else
if(exception != exception1)
exception.addSuppressed(exception1);
throw exception;
IOException e;
e;
e.printStackTrace();
}
}
可以看出try-with-resources为我们做了两件事:
-
添加了close
-
try块里面和close函数都可能抛出异常,这里会将try块抛出的异常压缩成Suppressed Exceptions,可以调用Throwable.getSuppressed方法取出被抑制的异常
而try-with-resources就是Java7为我们提供的一个语法糖啦。
所以,今后如果有在用到try-finally去处理资源的开启关闭的时候,记得有一种更加方便的方式:try-with-resources。
参考:
https://www.cnblogs.com/darrenqiao/p/9201357.html
关注公众号获取更多内容,有问题也可在公众号提问哦:
强哥叨逼叨
叨逼叨编程、互联网的见解和新鲜事