原文地址:http://blog.csdn.net/hengyunabc/article/details/18459463

这个所谓的try-with-resources,是个语法糖。实际上就是自动调用资源的close()函数。和Python里的with语句差不多。

例如:

  1. static String readFirstLineFromFile(String path) throws IOException {
  2. try (BufferedReader br = new BufferedReader(new FileReader(path))) {
  3. return br.readLine();
  4. }
  5. }

可以看到try语句多了个括号,而在括号里初始化了一个BufferedReader。

这种在try后面加个括号,再初始化对象的语法就叫try-with-resources。

实际上,相当于下面的代码(其实略有不同,下面会说明):

  1. static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
  2. BufferedReader br = new BufferedReader(new FileReader(path));
  3. try {
  4. return br.readLine();
  5. } finally {
  6. if (br != null) br.close();
  7. }
  8. }

很容易可以猜想到,这是编绎器自动在try-with-resources后面增加了判断对象是否为null,如果不为null,则调用close()函数的的字节码。

只有实现了java.lang.AutoCloseable接口,或者java.io.Closable(实际上继随自java.lang.AutoCloseable)接口的对象,才会自动调用其close()函数。

有点不同的是Java.io.Closable要求一实现者保证close函数可以被重复调用。而AutoCloseable的close()函数则不要求是幂等的。具体可以参考Javadoc。

下面从编绎器生成的字节码来分析下,try-with-resources到底是怎样工作的:

  1. public class TryStudy implements AutoCloseable{
  2. static void test() throws Exception {
  3. try(TryStudy tryStudy = new TryStudy()){
  4. System.out.println(tryStudy);
  5. }
  6. }
  7. @Override
  8. public void close() throws Exception {
  9. }
  10. }

TryStudy实现了AutoCloseable接口,下面来看下test函数的字节码:

  1. static test()V throws java/lang/Exception
  2. TRYCATCHBLOCK L0 L1 L2
  3. TRYCATCHBLOCK L3 L4 L4
  4. L5
  5. LINENUMBER 21 L5
  6. ACONST_NULL
  7. ASTORE 0
  8. ACONST_NULL
  9. ASTORE 1
  10. L3
  11. NEW TryStudy
  12. DUP
  13. INVOKESPECIAL TryStudy.<init> ()V
  14. ASTORE 2
  15. L0
  16. LINENUMBER 22 L0
  17. GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
  18. ALOAD 2
  19. INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
  20. L1
  21. LINENUMBER 23 L1
  22. ALOAD 2
  23. IFNULL L6
  24. ALOAD 2
  25. INVOKEVIRTUAL TryStudy.close ()V
  26. GOTO L6
  27. L2
  28. FRAME FULL [java/lang/Throwable java/lang/Throwable TryStudy] [java/lang/Throwable]
  29. ASTORE 0
  30. ALOAD 2
  31. IFNULL L7
  32. ALOAD 2
  33. INVOKEVIRTUAL TryStudy.close ()V
  34. L7
  35. FRAME CHOP 1
  36. ALOAD 0
  37. ATHROW
  38. L4
  39. FRAME SAME1 java/lang/Throwable
  40. ASTORE 1
  41. ALOAD 0
  42. IFNONNULL L8
  43. ALOAD 1
  44. ASTORE 0
  45. GOTO L9
  46. L8
  47. FRAME SAME
  48. ALOAD 0
  49. ALOAD 1
  50. IF_ACMPEQ L9
  51. ALOAD 0
  52. ALOAD 1
  53. INVOKEVIRTUAL java/lang/Throwable.addSuppressed (Ljava/lang/Throwable;)V
  54. L9
  55. FRAME SAME
  56. ALOAD 0
  57. ATHROW
  58. L6
  59. LINENUMBER 24 L6
  60. FRAME CHOP 2
  61. RETURN
  62. LOCALVARIABLE tryStudy LTryStudy; L0 L7 2
  63. MAXSTACK = 2
  64. MAXLOCALS = 3

从字节码里可以看出,的确是有判断tryStudy对象是否为null,如果不是null,则调用close函数进行资源回收。

再仔细分析,可以发现有一个Throwable.addSuppressed的调用,那么这个调用是什么呢?

其实,上面的字节码大概是这个样子的(当然,不完全是这样的,因为汇编的各种灵活的跳转用Java是表达不出来的):

  1. static void test() throws Exception {
  2. TryStudy tryStudy = null;
  3. try{
  4. tryStudy = new TryStudy();
  5. System.out.println(tryStudy);
  6. }catch(Throwable suppressedException) {
  7. if (tryStudy != null) {
  8. try {
  9. tryStudy.close();
  10. }catch(Throwable e) {
  11. e.addSuppressed(suppressedException);
  12. throw e;
  13. }
  14. }
  15. throw suppressedException;
  16. }
  17. }

有点晕是吧,其实很简单。使用了try-with-resources语句之后,有可能会出现两个异常,一个是try块里的异常,一个是调用close函数里抛出的异常。

当然,平时我们写代码时,没有关注到。一般都是再抛出close函数里的异常,前面的异常被丢弃了。

如果在调用close函数时出现异常,那么前面的异常就被称为Suppressed Exceptions,因此Throwable还有个addSuppressed函数可以把它们保存起来,当用户捕捉到close里抛出的异常时,就可以调用Throwable.getSuppressed函数来取出close之前的异常了。

总结:

使用try-with-resources的语法可以实现资源的自动回收处理,大大提高了代码的便利性,和mutil catch一样,是个好东东。

用编绎器生成的字节码的角度来看,try-with-resources语法更加高效点。

java.io.Closable接口要求一实现者保证close函数可以被重复调用,而AutoCloseable的close()函数则不要求是幂等的。

参考:

http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

http://docs.oracle.com/javase/7/docs/api/java/lang/AutoCloseable.html

http://docs.oracle.com/javase/7/docs/api/java/io/Closeable.html

Java7里try-with-resources分析--转的更多相关文章

  1. 在WebApi项目里使用MiniProfiler并且分析 Entity Framework Core

    在WebApi项目里使用MiniProfiler并且分析 Entity Framework Core 一.安装配置MiniProfiler 在现有的ASP.NET Core MVC WebApi 项目 ...

  2. Java7里try-with-resources分析

    这个所谓的try-with-resources,是个语法糖.实际上就是自动调用资源的close()函数.和Python里的with语句差不多. 例如: [java] view plain copy   ...

  3. php里进程创建和分析

    pcntl_fork()函数创建一个子进程,这个子进程仅PID(进程号) 和PPID(父进程号)与其父进程不同成功时,在父进程执行线程内返回产生的子进程的PID,在子进程执行线程内返回0.失败时,在 ...

  4. spring-mvc里的 <mvc:resources> 及静态资源访问

    在进行Spring MVC的配置时,通常我们会配置一个dispatcher servlet用于处理对应的URL.配置如下: <servlet> <servlet-name>Sp ...

  5. springMvc里的mvc:resources与静态资源的访问

    在进行Spring MVC的配置时,通常我们会配置一个dispatcher servlet用于处理对应的URL.配置如下:   <servlet>   <servlet-name&g ...

  6. JQuery里的原型prototype分析

    在 JavaScript 中,每个函数对象都有一个默认的属性 prototype,称为函数对象的原型成员,这个属性指向一个对象,称为函数的原型对象,当我们每定义了一个函数的时候,JavaScript ...

  7. 单例模式中的多线程分析synchronized

    谈到单例模式,我们立马会想到饿汉式和懒汉式加载,所谓饿汉式就是在创建类时就创建好了实例,懒汉式在获取实例时才去创建实例,即延迟加载. 饿汉式: 1 package com.bijian.study; ...

  8. 转:XBMC源代码分析

    1:整体结构以及编译方法 XBMC(全称是XBOX Media Center)是一个开源的媒体中心软件.XBMC最初为Xbox而开发,可以运行在Linux.OSX.Windows.Android4.0 ...

  9. Hadoop源代码分析

    http://wenku.baidu.com/link?url=R-QoZXhc918qoO0BX6eXI9_uPU75whF62vFFUBIR-7c5XAYUVxDRX5Rs6QZR9hrBnUdM ...

随机推荐

  1. 前端开发人员要注意的css规范,css命名。

    刚工作的时候也没注意关于css的规则,根据自己的心情想怎么用就怎么用,完成工作就好不会考虑代码的可读性,加载的性能,现在身为前端的一员就要有程序员的自我修养(嘿嘿,是不是很有责任感啊). 废话不多说, ...

  2. C语言中以文本方式读写文件时换行符转换的注意事项

    我们知道在UNIX下是没有回车符(\r)的,只有换行符(\n),而C语言诞生于UNIX(Linux即面向开源的UNIX,Mac OS也是UNIX发展而来的,而Windows是从MS-DOS发展而来,与 ...

  3. Hibernate框架学习(三)——实体规则、对象状态、一级缓存

    一.Hibernate中的实体规则 1.实体类创建的注意事项 1)持久化类提供无参数构造,因为在Hibernate的底层需要使用反射生成类的实例. 2)成员变量私有,提供公有的get和set方法,需提 ...

  4. Android使用Dribble Api

    使用Dribble提供的Api获取上面的设计分享 使用了Material Design.SceneTransitionAnimation 使用了Volley Gson 1. 申请Dribble开发者应 ...

  5. Linux下安装桌面

    1.         安装之前先测试是否有桌面 2.         建立yum源文件   3.         挂载好光盘(/rhel自己创建)   4.         使用yum list 查看 ...

  6. 【工作细节记录】维护项目中前端JS组件丢失后,应如何维护开发之启发

    事因: 我所维护的项目为旧项目,接手项目后并没有什么开发文档留下,导致很多时候一出现问题就需要自己去研究整个过程. 项目中一直使用一个"$.download()"的方法进行文件下载 ...

  7. Prototype-based programming

    Prototype-based programming is a style of object-oriented programming in which behaviour reuse (know ...

  8. 由一道面试题简单扩展 — setTimeout、闭包

    在一个前端公众号,看到这么一个号称简单的面试题: 1.以下程序输出什么? <script type="text/javascript"> function init() ...

  9. my.cnf配置样例

    [mysql] no-auto-rehash port = socket = /data/mysql/data/mysqld.sock [mysqld] user = mysql port = bas ...

  10. sklearn学习7-----决策树(tree)

    1.使用示例 2.树模型参数:[很多参数都是用来限制树过于庞大,即担心其过拟合] #  1.criterion  gini  or  entropy:用什么作为衡量标准 ( 熵值或者Gini系数 ). ...