使用try-with-resource取代try-catch-finally更便捷的开启关闭资源

648 阅读2分钟

JDK7后优化了try-catch-finally,有了try-with-resource语法糖可以简洁便利的关闭代码中打开的资源,下面我们用两个例子对比下JDK7之前打开资源关闭资源的方式

JDK7之前

    public static void main(String[] args) {
        //JDK1.7之前使用try-catch-finally关闭资源
        InputStream inputStream = null;
        try{
            inputStream = new FileInputStream("a.txt");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

可以明显看出,光是打开关闭一个stream流就如此多的代码嵌套,代码冗余而且不易阅读 下面我们看看JDK7以后是如何打开关闭资源的,简洁而且优雅

JDK7以后

        //JDK1.7之后使用try-with-resource关闭资源
        try(InputStream inputStream = new FileInputStream("a.txt")){
            //TODO inputStream流的使用逻辑
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

上面的代码跟之前的代码实现了同样的功能,代码量却大大减少了。 我已经会用了,喔!真的好方便

等等!!!!仔细观察

问题:

上述代码中没有对打开的inpustream流进行关闭,那么它是怎么关闭的呢?

解答:

让我们去看一下编译出来的.class文件是什么样,对比下try-with-resource和try-catch-finally编译出来有什么差别。

前方高能·····!!!!

使用try-with-resource编译出来的.class文件

    public void resouceOpen() {
        try {
            InputStream inputStream = new FileInputStream("a.txt");
            Object var2 = null;
            if (inputStream != null) {
                if (var2 != null) {
                    try {
                        inputStream.close();
                    } catch (Throwable var4) {
                        ((Throwable)var2).addSuppressed(var4);
                    }
                } else {
                    inputStream.close();
                }
            }
        } catch (FileNotFoundException var5) {
            var5.printStackTrace();
        } catch (IOException var6) {
            var6.printStackTrace();
        }

    }

这不就是我以前那种写法吗!沉思~~~~,那···Object var2 = null;这个对象是干鸡毛的呀!
经过一顿操作(ps百度),我恍然大悟,原来是为了解决屏蔽异常的问题的呀! 解释:在某些情况下,异常会被覆盖,比如我一段代码中出现了两个异常,但是出现了异常屏蔽,只打印出来了一个异常。使用try-with-resource后会打印出来所有的异常,Suppressed:标识出被屏蔽的异常。

java.lang.Exception: 使用resourceA出现异常
	at com.example.pagehelperdemo.controller.TestController$RescourceA.useResourceA(TestController.java:47)
	at com.example.pagehelperdemo.controller.TestController.useCustomResource(TestController.java:39)
	at com.example.pagehelperdemo.controller.TestController.main(TestController.java:17)
	Suppressed: java.lang.Exception: 关闭resourceA出现异常
		at com.example.pagehelperdemo.controller.TestController$RescourceA.close(TestController.java:51)
		at com.example.pagehelperdemo.controller.TestController.useCustomResource(TestController.java:40)
		... 1 more