目录
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");
}
}
}
从反编译的结果可以得出以下结论:
- 无论try{...}语句块是否报错,在try(...)中声明的资源都会依次关闭;
- try(...)中声明的资源,后声明的先关闭;
- try(...)中声明的资源互不影响,前一个资源释放报错不影响后一个资源的释放。