Java7的try-with-resources声明

java

看《Effective Java》第三版的时候,看到了其中建议将try-finally替换为try-with-resources。这个语法糖还算有意思,特此成文。

用法辨析

Java库中有很多资源需要手动关闭,比如InputStream、OutputStream、java.sql.Connection等等。在此之前,通常是使用try-finally的方式关闭资源;Java7之后,推出了try-with-resources声明来替代之前的方式。 try-with-resources 声明要求其中定义的变量实现 AutoCloseable 接口,这样系统可以自动调用它们的close方法,从而替代了finally中关闭资源的功能。

举个栗子,下面是一个复制文件的方法,按照原本try-catch-finally的写法:

// 一个简单的复制文件方法。

public static void copy(String src, String dst) {

InputStream in = null;

OutputStream out = null;

try {

in = new FileInputStream(src);

out = new FileOutputStream(dst);

byte[] buff = new byte[1024];

int n;

while ((n = in.read(buff)) >= 0) {

out.write(buff, 0, n);

}

} catch (IOException e) {

e.printStackTrace();

} finally {

if (in != null) {

try {

in.close();

} catch (IOException e) {

e.printStackTrace();

}

}

if (out != null) {

try {

out.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

可以看出,这种实现非常的丑陋。

下面来看使用了try-with-resources后的效果:

public static void copy(String src, String dst) {

try (InputStream in = new FileInputStream(src);

OutputStream out = new FileOutputStream(dst)) {

byte[] buff = new byte[1024];

int n;

while ((n = in.read(buff)) >= 0) {

out.write(buff, 0, n);

}

} catch (IOException e) {

e.printStackTrace();

}

}

try-with-resources将会自动关闭try()中的资源,并且将先关闭后声明的资源。

如果不catch IOException就更加清爽了:

public static void copy(String src, String dst) throws IOException {

try (InputStream in = new FileInputStream(src);

OutputStream out = new FileOutputStream(dst)) {

byte[] buff = new byte[1024];

int n;

while ((n = in.read(buff)) >= 0) {

out.write(buff, 0, n);

}

}

}

原理分析

那么try-with-resources有什么神奇之处呢?到底做了什么呢?

我们先来看下AutoCloseable接口:

public interface AutoCloseable {

void close() throws Exception;

}

其中仅有一个close方法,实现AutoCloseable接口的类将在close方法中实现其关闭资源的功能。

而try-with-resources其实是个语法糖,它将在编译时编译成关闭资源的代码。我们将上述例子中的代码编译成class文件,再反编译回java文件,就能看到如下代码:

public static void copy(String var0, String var1) throws IOException {

FileInputStream var2 = new FileInputStream(var0);

Throwable var3 = null;

try {

FileOutputStream var4 = new FileOutputStream(var1);

Throwable var5 = null;

try {

byte[] var6 = new byte[1024];

int var7;

while((var7 = var2.read(var6)) >= 0) {

var4.write(var6, 0, var7);

}

} catch (Throwable var29) {

var5 = var29;

throw var29;

} finally {

if (var4 != null) {

if (var5 != null) {

try {

// 关闭FileOutputStream

var4.close();

} catch (Throwable var28) {

var5.addSuppressed(var28);

}

} else {

var4.close();

}

}

}

} catch (Throwable var31) {

var3 = var31;

throw var31;

} finally {

if (var2 != null) {

if (var3 != null) {

try {

// 关闭FileInputStream

var2.close();

} catch (Throwable var27) {

var3.addSuppressed(var27);

}

} else {

var2.close();

}

}

}

}

除却处理异常相关的代码,其实就是调用了资源的close方法。

不过不得不说这个语法糖挺甜,真香。

1人点赞

Android成长之路

作者:聪明叉

链接:https://www.jianshu.com/p/6adb6dbc4140

来源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

以上是 Java7的try-with-resources声明 的全部内容, 来源链接: utcz.com/z/394443.html

回到顶部