原文地址:https://www.cnblogs.com/itZhy/p/7636615.html
为了确保外部资源一定要被关闭,通常关闭代码被写入finally代码块中,同时还必须注意到关闭资源时可能抛出的异常,
例如,我们经常使用的关闭资源的代码
1 public static void main(String[] args) {
2 FileInputStream inputStream = null;
3 try {
4 inputStream = new FileInputStream(new File("test"));
5 System.out.println(inputStream.read());
6 } catch (IOException e) {
7 throw new RuntimeException(e.getMessage(), e);
8 } finally {
9 if (inputStream != null) {
10 try {
11 inputStream.close();
12 } catch (IOException e) {
13 throw new RuntimeException(e.getMessage(), e);
14 }
15 }
16 }
17 }
当一个外部资源的句柄对象(比如FileInputStream对象)实现了AutoCloseable接口,那么就可以将上面的板式代码简化为如下形式:
1 public static void main(String[] args) {
2 try (FileInputStream inputStream = new FileInputStream(new File("test"))) {
3 System.out.println(inputStream.read());
4 } catch (IOException e) {
5 throw new RuntimeException(e.getMessage(), e);
6 }
7 }
try-with-resource并不是JVM虚拟机的新增功能,只是JDK实现了一个语法糖,当你将上面代码反编译后会发现,代码中有一处对异常的特殊处理:
var2.addSuppressed(var11);
这是try-with-resource语法涉及的另外一个知识点,叫做异常抑制。当对外部资源进行处理(例如读或写)时,如果遭遇了异常,且在随后的关闭外部资源过程中,又遭遇了异常,那么你catch到的将会是对外部资源进行处理时遭遇的异常,关闭资源时遭遇的异常将被“抑制”但不是丢弃,通过异常的getSuppressed方法,可以提取出被抑制的异常。
总结
1、当一个外部资源的句柄对象实现了AutoCloseable接口,JDK7中便可以利用try-with-resource语法更优雅的关闭资源,消除板式代码。
2、try-with-resource时,如果对外部资源的处理和对外部资源的关闭均遭遇了异常,“关闭异常”将被抑制,“处理异常”将被抛出,但“关闭异常”并没有丢失,而是存放在“处理异常”的被抑制的异常列表中。