接口
AutoCloseable
1. 概述
可能保存资源的对象(例如文件),直到关闭。AutoCloseable对象的close()方法在退出try- with-resources块时被自动调用,该块在资源规范头中声明了该对象。此构造确保及时释放,避免资源耗尽异常和可能出现的错误。
即使不是所有的子类或实例都拥有可释放的资源,基本类也可以实现自动关闭。对于必须具有完全通用性的代码,或者当已知AutoCloseable实例需要资源释放时,建议使用try- with-resources结构。然而,在用非IO流时没有必要用try-with-resources。
2. 源码解析
public interface AutoCloseable {
/**
* 关闭该资源,放弃任何潜在资源。
*此方法将自动在try-with-resources语句管理的对象上调用。
*
* 虽然该接口方法被声明为抛出异常,但强烈鼓励实现者声明close()方法的具体实现,
* 以抛出更多特定的异常,或者如果关闭操作不能失败,也不抛出异常。
*
* 关闭操作可能失败的情况需要实现者仔细注意。在抛出异常之前,强烈建议放弃
* 底层资源并在内部标记资源。close方法不太可能被多次调用,因此这确保了资源
* 的及时发布。此外,它还减少了资源包装或被其他资源包装时可能出现的问题。
*
*
* @throws Exception 如果资源不能关闭
*/
void close() throws Exception;
}
3. 总结
已知子接口,和实现类太多了就没有写在上面,在这挑几个常见的来说说,
子接口:Closeable, Connection
Closeable是在java.io包里的也就一个方法。
public interface Closeable extends AutoCloseable{
public void close() throws IOException;
}
用处也是关闭这个流并释放与之关联的任何系统资源。如果流已经关闭然后调用这个方法没有效果。
Connection是在java.sql包下
public interface Connection extends Wrapper, AutoCloseable {
void close() throws SQLException
}
用处是立即释放此 Connection 对象的数据库和 JDBC 资源,而不是等待它们被自动释放。
这些方法都遵循了 实现者声明 close()方法的具体实现,以抛出更多特定的异常,或者如果关闭操作不会失败,也不抛出异常。
实现类
BufferedInputStream
此类也是java.io包下的
public class BufferedInputStream extends FilterInputStream {
protected volatile byte buf[];
private static final
AtomicReferenceFieldUpdater<BufferedInputStream, byte[]> bufUpdater =
AtomicReferenceFieldUpdater.newUpdater
(BufferedInputStream.class, byte[].class, "buf");
// 带参数构造函数
public BufferedInputStream(InputStream in, int size) {
super(in);
if (size <= 0) {
throw new IllegalArgumentException("Buffer size <= 0");
}
buf = new byte[size];
}
public void close() throws IOException {
byte[] buffer;
while ( (buffer = buf) != null) {
if (bufUpdater.compareAndSet(this, buffer, null)) {
InputStream input = in;
in = null;
if (input != null)
input.close();
return;
}
// 如果在fill()中装入新的buf,则需要重试
}
}
close执行步骤
定义一个byte数组 buffer,把buf 数组赋值给buffer。如果buffer不为null,就把buffer更新为null。
更新成功 ,定义一个InputStream对象,并把 in赋值给input,然后让in指向null。如果input不为空 就执行 input.close(),最后跳出。
4. 对try-with-resources和传统释放资源对比
public class AutoCloseableTest {
/**
* 演示传统的资源释放方式
*/
@Test
public void traditionTest(){
SubAutoCloseable subAutoCloseable = null;
try {
subAutoCloseable = new SubAutoCloseable();
subAutoCloseable.readResouse();
}catch (Exception e){
e.printStackTrace();
}finally {
if(subAutoCloseable != null){
try {
subAutoCloseable.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* JDK1.7 新特性 try-with-resources
*/
@Test
public void test(){
try(SubAutoCloseable subAutoCloseable = new SubAutoCloseable()){
subAutoCloseable.readResouse();
}catch (Exception e){
e.printStackTrace();
}
}
public class SubAutoCloseable implements AutoCloseable{
public void readResouse(){
System.out.println("正在读取资源");
}
@Override
public void close() throws Exception {
System.out.println("关闭资源");
}
}