目录

AutoCloseable接口

接口功能

常见的实现类

try-with-resources块语句

原理分析


AutoCloseable接口

接口功能

全称java.lang.AutoCloseable,jdk1.7引入、官方文档说明:

一个可以保存资源(如文件或套接字句柄)直到它被关闭的对象。AutoCloseable对象的close()方法在退出资源块(try-with-resources block)时被自动调用,资源块是在资源规范头中声明的对象。这种构造确保了快速释放,避免了可能发生的资源耗尽异常和错误。

常见的实现类

BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter, ByteArrayInputStream, ByteArrayOutputStream, FileInputStream, FileOutputStream, FileReader, FileWriter,ObjectInputStream, ObjectOutputStream, OutputStream, OutputStream, OutputStream, OutputStreamWriter, Socket......等还有很多,具体参照javadoc。

try-with-resources块语句

public class AutoCloseableTest implements AutoCloseable {

	private String name;

	public AutoCloseableTest(String name) {
		this.name = name;
	}
	@Override
	public void close() throws Exception {
		System.out.println("I'm " + name + " and to closing");
		throw new Exception("close " + name + " exception");
	}

	public static void main(String[] args) {

		try (/* 声明需要自动释放的资源:
				1、必须实现java.lang.AutoCloseable接口;
				2、多个资源分号分隔;
				3、这里声明的资源不能再被赋值,既被隐式声明为final。
				*/
				AutoCloseableTest res1 = new AutoCloseableTest("res1");
				AutoCloseableTest res2 = new AutoCloseableTest("res2");
		) {
			
			System.out.println("do something");
			throw new Exception("do something exception");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			System.out.println("do finally block");
		}
	}
}

执行结果

do something
I'm res2 and to closing
I'm res1 and to closing
java.lang.Exception: do something exception
	at jdk.source.read.java.lang.AutoCloseableTest.main(AutoCloseableTest.java:28)
	Suppressed: java.lang.Exception: close res2 exception
		at jdk.source.read.java.lang.AutoCloseableTest.close(AutoCloseableTest.java:13)
		at jdk.source.read.java.lang.AutoCloseableTest.main(AutoCloseableTest.java:29)
	Suppressed: java.lang.Exception: close res1 exception
		at jdk.source.read.java.lang.AutoCloseableTest.close(AutoCloseableTest.java:13)
		at jdk.source.read.java.lang.AutoCloseableTest.main(AutoCloseableTest.java:29)
do finally block

原理分析

对上面的类编译后的class文件进行反编译(在线反编译工具:http://javare.cn/):

public class AutoCloseableTest implements AutoCloseable {

   private String name;

   public AutoCloseableTest(String name) {
      this.name = name;
   }

   public void close() throws Exception {
      System.out.println("I\'m " + this.name + " and to closing");
      throw new Exception("close " + this.name + " exception");
   }

   public static void main(String[] args) {
      try {
         Throwable e = null;
         Object var2 = null;

         try {
            AutoCloseableTest res1 = new AutoCloseableTest("res1");

            try {
               AutoCloseableTest res2 = new AutoCloseableTest("res2");

               try {
                  System.out.println("do something");
                  throw new Exception("do something exception");
               } finally {
                  if(res2 != null) {
                     res2.close();
                  }

               }
            } catch (Throwable var27) {
               if(e == null) {
                  e = var27;
               } else if(e != var27) {
                  e.addSuppressed(var27);
               }

               if(res1 != null) {
                  res1.close();
               }

               throw e;
            }
         } catch (Throwable var28) {
            if(e == null) {
               e = var28;
            } else if(e != var28) {
               e.addSuppressed(var28);
            }

            throw e;
         }
      } catch (Exception var29) {
         var29.printStackTrace();
      } finally {
         System.out.println("do finally block");
      }

   }
}

从反编译的结果可以得出以下结论:

  1. 无论try{...}语句块是否报错,在try(...)中声明的资源都会依次关闭;
  2. try(...)中声明的资源,后声明的先关闭;
  3. try(...)中声明的资源互不影响,前一个资源释放报错不影响后一个资源的释放。