AutoCloseable & Closable 是 Java IO流中的两个接口,后者继承自前者。都只有一个 close 方法。
语法糖
AutoCloseable 出现在 Java7 中,它的作用是:减少代码的繁冗度,对于需要关闭的资源使用一种“try-with-resource”方式关闭,这是一个语法糖,即便于程序员编写代码的一种特制语法(Ps : 语法糖,吃多了也会牙齿坏掉)语法如下:
//try-with-resource
String readFileLine(String path) throws IOException
{
try (BufferedReader br = new BufferedReader(new FileReader(path)))
{
return br.readLine();
}
}
//经典写法
String readFileLine(String path) throws IOException
{
BufferedReader br = null;
try
{
br = new BufferedReader(new FileReader(path));
return br.readLine();
}
catch(IOException ex){}
finally
{
if (br != null) br.close();
}
}
AutoCloseable 是为了支持 try-with-resource 语法出现的工具,实现这个接口的资源类意味着该类可以使用 try-with-resource,否则不能使用。
Who call close?
实际上这个语法糖在代码编译时会被编译为“经典写法”,可以使用如下的代码验证最终 close 方法的调用者是资源类使用所在地。
public class TryWithResource implements AutoCloseable {
public TryWithResource() {
// TODO Auto-generated constructor stub
}
@Override
public void close() throws Exception
{
// TODO Auto-generated method stub
getCaller();
}
public void end()
{
System.out.println("use end...");
}
public void getCaller() {
StackTraceElement stack[] = Thread.currentThread().getStackTrace();
for (StackTraceElement ste : stack) {
System.out.println(
"called by" + ste.getClassName() + "." + ste.getMethodName() + "/" + ste.getFileName());
}
}
public static void main(String [] args)
{
try(TryWithResource twr = new TryWithResource())
{
twr.end();
}
catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("close error...");
}
}
}
What else?
AutoCloseable 是一个更高抽象层次的接口,不一定用在 IO 上,所以它里面的 close 方法抛出的异常是 Exception,而非 IOException。
Closable 是一个被具现化了的接口:只用作 IO 流上,所以 close 方法抛出的异常是 IOException。
最后一个区别是,Closeable 方法被设计为可重复调用:可以被自动调用:故 Closeable 继承了 AutoCloseable,也可以被手动调用,所以实现了 Closeable 的类的 close 方法必须要被设计为可重复被多次调用。而 AutoCloseabe 不具体这个性质,它就是被设计为“自动关闭”的,所以实现这个接口的类的 close 方法不应该被设计为“可被多次调用”。