美文网首页
java 7 新特性 try-with-resources

java 7 新特性 try-with-resources

作者: jieyao | 来源:发表于2017-05-24 15:18 被阅读0次

诸如流、文件等系统资源,当其被打开时,需要手动关闭,要不必将引起一场大灾害。

传统的try cache finally

在java7之前,我们可以使用finally来确保资源被关闭,例如:

static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
  BufferedReader br = new BufferedReader(new FileReader(path));
  try {
    return br.readLine();
  } finally {
    if (br != null) 
        br.close();
  }
}

但是如果br.readLine()有异常,br.close()也有异常抛出,由于一次只能抛一次异常,try的异常会被抑制,finally的异常会被抛出,导致异常丢失。以下是具体演示:

public class Connection implements AutoCloseable {

    public void sendData() throws Exception {
        throw new Exception("send data");
    }
    @Override
    public void close() throws Exception {
        throw new Exception("close");
    }
}
public class TryWithResource {

    public static void main(String[] args) {
        try{
            test();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void test()throws Exception{
        Connection conn = null;
        try{
            conn = new Connection();
            conn.sendData();
        } finally{
            if(conn !=null) {
                conn.close();
            }
        }
    }
}

运行结果如下:

java.lang.Exception: close
    at cn.wangjy.study.trywithresources.Connection.close(Connection.java:18)
    at cn.wangjy.study.trywithresources.TryWithResource.test(TryWithResource.java:84)
    at cn.wangjy.study.trywithresources.TryWithResource.main(TryWithResource.java:71)
    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:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

用try-with-resources实现

JAVA 7之后,我们盼来福音,再也不需要在finally里面写一堆if(xxx !=null)xxx.close()的代码,只要资源实现了AutoCloseable或者Closeable接口,try-with-resources能帮其自动关闭。将以上的代码改写为try-with-resources

public class TryWithResource {

    public static void main(String[] args) {
        try(Connection conn =new Connection()) {
            conn.sendData();
        }catch(Exception e) {
            e.printStackTrace();
        }
    }
}

运行结果如下:

java.lang.Exception: send data
    at cn.wangjy.study.trywithresources.Connection.sendData(Connection.java:13)
    at cn.wangjy.study.trywithresources.TryWithResource.main(TryWithResource.java:71)
    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:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
    Suppressed: java.lang.Exception: close
        at cn.wangjy.study.trywithresources.Connection.close(Connection.java:18)
        at cn.wangjy.study.trywithresources.TryWithResource.main(TryWithResource.java:72)
        ... 5 more

可以看到,代码编写也十分简洁。虽然我们没有用finally的代码块写明close(),但是程序仍然会自动执行close()方法,并且异常信息也没有丢失。信息中多了一个Suppressed的提示,附带上close的异常。这个异常其实由两个异常组成, 执行close()的异常是被Suppressed的异常。

原理是什么呢?

反编译了TryWithResource的class文件,代码如下

public static void main(String[] args) {
        try {
            Connection conn = new Connection();
            Throwable localThrowable3 = null;
            try {
                conn.sendData();
            } catch (Throwable localThrowable1) {
                localThrowable3 = localThrowable1;
                throw localThrowable1;
            } finally {
                if (conn != null) if (localThrowable3 != null) try {
                    conn.close();
                } catch (Throwable localThrowable2) {
                    localThrowable3.addSuppressed(localThrowable2);
                }
                else conn.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

可见,编译器在编译的时候自动帮我们加了finally块,并添加了资源的close方法,所以例子的close会在运行的时候被执行。细心的你发现了吗,代码中还多了localThrowable3.addSuppressed(localThrowable2)的方法。java7之后,Throwable类新增了addSuppressed方法,支持将一个异常附加到另一个异常身上,从而避免异常屏蔽。这样输出的异常信息会附带Suppressed的提示,参考上图的运行结果。

try-with-resources 也支持声明多个资源

public static void main(String[] args) {
        try (FileInputStream fin = new FileInputStream(new File("input.txt")); 
             FileOutputStream fout = new FileOutputStream(new File("out.txt"));
             GZIPOutputStream out = new GZIPOutputStream(fout)) {
            byte[] buffer = new byte[4096];
            int read;
            while ((read = fin.read(buffer)) != -1) {
                out.write(buffer, 0, read);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

资源关闭会按声明时的相反顺序被执行。

参考:
http://docs.oracle.com/javase/7/docs/technotes/guides/language/try-with-resources.html
http://www.tuicool.com/articles/JvQRBri

相关文章

  • java 7 新特性 try-with-resources

    诸如流、文件等系统资源,当其被打开时,需要手动关闭,要不必将引起一场大灾害。 传统的try cache final...

  • Java11的新特性

    Java语言特性系列 Java5的新特性 Java6的新特性 Java7的新特性 Java8的新特性 Java9的...

  • Java15的新特性

    Java语言特性系列 Java5的新特性 Java6的新特性 Java7的新特性 Java8的新特性 Java9的...

  • Java12的新特性

    Java语言特性系列 Java5的新特性 Java6的新特性 Java7的新特性 Java8的新特性 Java9的...

  • 增强 try (Try-with-resources)

    此心光明,亦复何言 Try-with-resources Try-with-resources是Java7出现的一...

  • Java7新特性及使用

    Java7新特性及使用 新特性列表 以下是Java7中的引入的部分新特性。 switch支持String try-...

  • 夯实 Java 基础3 - 异常机制

    Java 提供了完备的异常机制,在 Java7 引入了 try-with-resources 语法糖。 一、Jav...

  • java try-with-resource语句使用

    定义 JDK7之后,Java多了个新的语法:try-with-resources语句,可以理解为是一个声明一个或多...

  • java进阶

    Invokedynamic:Java的秘密武器 在Java 7的发布版中包含了多项新的特性,这些特性乍看上去Jav...

  • Apache和Spring提供的StopWatch执行时间监视器

    相关阅读 【小家java】java5新特性(简述十大新特性) 重要一跃【小家java】java6新特性(简述十大新...

网友评论

      本文标题:java 7 新特性 try-with-resources

      本文链接:https://www.haomeiwen.com/subject/jphoxxtx.html