java8学习第二篇:try-with-resources

Java8里的一个新语法特性:try-with-resources。

这个语法特性其实从java7里就有了,不过java8的sample里依然有这个。

try-with-resources的特性就是,在try( …)里声明的资源,会在try-catch代码块结束后自动关闭掉。

废话不说,先上代码后分析。

public class AutoCloseTest {
    public static void main(String[] args)  {
        testNormalOutput(args[0]);
        testAutoCloseWithTryCatch(args[1]);
    }

    private static void testNormalOutput(String filepath){
        OutputStream global_out = null;
        BufferedWriter writer ;
        try {
            OutputStream out = out = new FileOutputStream(filepath);
            global_out = out;
            out.write((filepath + "inside try catch block").getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }

        try{
            if(global_out!=null){
                global_out.write("  \t\r outside try catch block".getBytes());
                global_out.close();
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    private static void testAutoCloseWithTryCatch(String filepath){
        OutputStream global_out = null;
        try(OutputStream out = new FileOutputStream(filepath);) {
            global_out = out;
            out.write((filepath+"inside try catch block").getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }
        try{
            if(global_out!=null){
                global_out.write("  \t\r outside try catch block".getBytes());
                global_out.close();
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

运行

java AutoCloseTest d:/a.txt d:/b.txt

然后发现

a.txt里的内容是

d:/a.txt inside try catch block  	outside try catch block


b.txt里的内容是

d:/b.txt inside try catch block

没错,b.txt的后半段代码没有执行 同时控制台还打印出

java.io.IOException: Stream Closed
	at java.io.FileOutputStream.writeBytes(Native Method)
	at java.io.FileOutputStream.write(FileOutputStream.java:294)
	at trywithresources.AutoCloseTest.testAutoCloseWithTryCatch(AutoCloseTest.java:46)
	at trywithresources.AutoCloseTest.main(AutoCloseTest.java:11)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:483)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

这是因为在testAutoCloseWithTryCatch方法里,global_out所指向的out对象已经在第一次try-catch之后被关闭了 在第二次对这个已经关闭的流里输出内容时,就会报Stream Closed错误。

——————–*************************———————–********************

那么try-with-resources是如何工作的呢?它和finally的工作谁在前呢?我们可以做一个小测试

    private static void testAutoClose() {
        AutoCloseable global_obj1 = null;
        AutoCloseable global_obj2 = null;
        try(AutoCloseable obj1 = new AutoClosedImpl("obj1");
            AutoCloseable obj2 = new AutoClosedImpl("obj2");){
            global_obj1= obj1;
            int i = 1/0;
            global_obj2= obj2;
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try{
                System.out.println("before finally close");
                if(global_obj1!=null){
                    global_obj1.close();
                }
                if(global_obj2!=null){
                    global_obj2.close();
                }
                System.out.println("after finally close");
            }   catch(Exception e){
                e.printStackTrace();
            }
        }
    }

    private static class AutoClosedImpl implements AutoCloseable{
        private String name;
        public AutoClosedImpl(String name){
            this.name = name;
        }
        @Override
        public void close() throws Exception {
            System.out.println(name+" closing");
        }
    }

执行testAutoClose()方法,会打印出如下结果

obj2 closing
obj1 closing
before finally close
obj1 closing
after finally close
java.lang.ArithmeticException: / by zero
    at trywithresources.AutoCloseTest.testAutoClose(AutoCloseTest.java:60)
    at trywithresources.AutoCloseTest.main(AutoCloseTest.java:12)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

从上述代码我们可以观测四件事 1. 凡是实现了AutoCloseable接口的类,在try()里声明该类实例的时候,在try结束后,close方法都会被调用 2. try结束后自动调用的close方法,这个动作会早于finally里调用的方法。 3. 不管是否出现异常(int i=1/0会抛出异常),try()里的实例都会被调用close方法 4. 越晚声明的对象,会越早被close掉。

    原文作者:java吧
    原文地址: https://blog.csdn.net/java8cn/article/details/22761855
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞