Closeable
和AutoCloseable
都是接口,且都只定义了一个close()
方法。
Closeable
: 定义于 java.io
包中,于JDK5
添加;
AutoCloseable
: 定义于java.lang
包中, 于JDK7
添加;
AutoCloseable.java
public interface AutoCloseable{
void close() throws Exception;
}
从JDK7
开始,Closeable
扩展了AutoCloseable
Closeable.java
public interface Closeable extends AutoCloseable {
public void close() throws IOException;
}
因此从JDK7
开始,Closeable
和AutoCloseable
具有相同的功能,因此下面只介绍AutoCloseable
。
AutoCloseable
是一个接口,只定义了一个close()
方法。接口是什么?是为了给某些类实现的,它强制要求这个类提供接口定义的方法。所有实现AutoCloseable
接口的类都必须提供close()
方法。
那什么样的类需要实现AutoCloseable
(Closeable
)接口呢? 看看它定义的方法, close()
。看名字就知道所有实现这个接口的类都必须提供关闭的方法,关闭的自然是资源, 比如各类输入输出流资源, Socket
等。
常见的实现了AutoCloseable
接口的类有:
BufferedInputStream
, BufferedOutputStream
BufferedReader
, BufferedWriter
FileInputStream
, FileOutputStream
FileReader
, FileWriter
InputStream
, OutputStream
PrintWriter
, PrintStream
Reader
, Writer
Scanner
, SSLServerSocker
, SSLSocket
等等等等
在JDK1.7
以前,如果我们要用到上面的这些资源类,因为没有他们没有实现AutoCloseable
接口, 正常的做法是需要使用try-finally
结构, 在finally
中手动的释放资源:
//JDK1.7之前,释放资源方式
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream("");
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
这么做的坏处是:
1、自己要手动写代码做关闭的逻辑;
2、有时候还会忘记关闭一些资源;
3、关闭代码的逻辑比较冗长,不应该是正常的业务逻辑需要关注的;
为了解决需要手动释放资源的问题, 在JDK1.7
中引入了AutoCloseable
接口,凡是实现了这个接口的资源类在使用的时候采用另外一种语法,可以使得免于手动关闭这些资源类。
AutoCloseable
接口的资源类对于实现了AutoCloseable
接口的类的实例,将其放到try
后面的小括号中,这种语法我们称之为:带资源的try
语句,在try
结束的时候,会自动将这些资源关闭(调用close
方法)。
//1.7之后,只要实现了AutoCloseable接口
try (FileInputStream fileInputStream2 = new FileInputStream("");
Reader rd = new Reader()) {
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
注意这里申请资源的语句放在了紧跟着try
的小括号中,这属于JDK1.7
的新语法。只要用这样的语法申请实现了AutoCloseable
接口的资源类,就无需使用finally
块手动释放这些资源。
带资源的try
语句的3个关键点:
try
语句管理的资源必须是实现了AutoCloseable
接口的类的对象。try
代码中声明的资源被隐式声明为final
。AutoCloseable
接口对于自己定义的资源类,如果也想像FileInputStream
一样在使用的时候用带资源的try
语句实现自动释放,做法就很显然: 让这个类去实现AutoCloseable
接口并重写close()
方法, 在重写的close()
方法中提供释放资源的语句。
class MyResource implements AutoCloseable {
/**
对这个接口的实现,规范强烈建议close()是幂等的,也就是说多次调用close()方法和一次调用的结果是一样的。
*/
@Override
public void close() throws Exception {
//添加释放资源的语句
System.out.println("close resource");
}
public void readResource() {
//提供资源的方法
System.out.println("read resource");
}
}
这样定义了MyResource
类后,就可以像如下方式使用它:
//示例,使用自己定义的资源类,它实现了AutoCloseable接口
try (MyResource myResource = new MyResource()) {
myResource.readResource();
myResource2.readResource();
} catch (Exception e) {
e.printStackTrace();
}
虽然在JDK1.7
之后AutoCloseable
和Closeable
具有一样的功能,但一般实现自己的资源类的时候我们让它实现AutoCloseable
类。Closeable
比AutoCloseable
更早出现(JDK5
),在JDK7
之前它提供了一套关闭资源的方法,但是后来的AutoCloseable
可以用更好的方法来关闭资源,于是从JDK7
开始弃用了之前Closeable
接口关闭资源的方法,而让它去扩展AutoCloseable
接口,这样先前实现Closeable
类的方法也可以过度到AutoCloseable
的解决方案中来。
需要注意的是AutoCloseable
定义在java.lang
包中,这个包在java
启动时自动加载到环境,所以使用AutoCloseable
时无需额外引包;而Closeable
定义在java.io
中,如果要使用这个接口需要手动引入java.io.Closeable
;
Java 基础 AutoCloseable & Closeable
原文:https://www.cnblogs.com/greatLong/p/11951739.html