原文地址: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时,如果对外部资源的处理和对外部资源的关闭均遭遇了异常,“关闭异常”将被抑制,“处理异常”将被抛出,但“关闭异常”并没有丢失,而是存放在“处理异常”的被抑制的异常列表中。