10.2.7 Java9增强的自动关闭资源的try语句

Java7自动关闭资源的try语句

Java 7增强了try语句的功能:它允许在try关键字后紧跟一对圆括号,圆括号可以声明、初始化一个或多个资源。此处的资源指的是那些必须在程序结束时显式关闭的资源(比如数据库连接网络连接等),try语句在该语句结束时 自动关闭 这些资源

什么样的资源可以让try语句自动关闭

为了保证try语句可以正常关闭资源,这些资源实现类必须实现AutoCloseableCloseable接口,实现这两个接口就必须实现close()方法。

Closeable和AutoCloseable的区别

CloseableAutoCloseable的子接口,可以被自动关闭的资源类要么实现AutoCloseable接口,要么实现Closeable接口。

  • Closeable接口里的close()方法声明抛出了IOException,因此它的实现类在实现close()方法时只能声明抛出IOException或其子类
  • AutoCloseable接口里的close()方法声明抛出了Exception,因此它的实现类在实现close()方法时可以声明拋出任何异常

程序示例

下面程序示范了如何使用自动关闭资源的try语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.io.*;

public class AutoCloseTest
{
public static void main(String[] args)
throws IOException
{
try (
// 声明、初始化两个可关闭的资源
// try语句会自动关闭这两个资源。
BufferedReader br = new BufferedReader(
new FileReader("AutoCloseTest.java"));
PrintStream ps = new PrintStream(new
FileOutputStream("a.txt"));
)
{
// 使用两个资源
System.out.println(br.readLine());
ps.println("庄生晓梦迷蝴蝶");
}
}
}

上面程序中try后面圆括号中的代码分别声明、初始化了两个IO流,由于BufferedReaderPrintStream都实现了Closeable接口,而且它们放在try语句中声明、初始化,所以try语句会自动关闭它们。因此上面程序是安全的。

自动关闭资源的try语句可以没有catch块也可以没有finally块

自动关闭资源的try语句相当于包含了隐式的finally(这个finally块用于关闭资源),因此这个try语句可以既没有catch块,也没有finally块

Java 7几乎所有的资源类都可以自动关闭

Java 7几乎把所有的“资源类”(包括文件IO的各种类、JDBC编程的ConnectionStatement等接口)进行了改写,改写后资源类都实现了AutoCloseableCloseable接口。

如果程序需要,自动关闭资源的try语句后也可以带多个catch块和一个finally块。

Java9对自动关闭资源的try语句的增强

Java9再次增强了这种try语句,Java9不要求在try后的圆括号内声明并创建资源。

Java9只需要将资源的引用变量放在try后的括号里即可

Java9允许将需要自动关闭的资源的引用变量放在try后的圆括号内,只要这些引用变量有final修饰或者是有效的final( effectively final)即可

什么是有效的final

只要不对该变量重新赋值,按该变量就是有效的final。

程序示例

上面程序在Java9中可改写为如下形式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.io.*;

public class AutoCloseTest2 {
public static void main(String[] args) throws IOException {
// 有final修饰的资源
final BufferedReader br = new BufferedReader(new FileReader("AutoCloseTest.java"));
// 没有显式使用final修饰,但只要不对该变量重新赋值,按该变量就是有效的final
PrintStream ps = new PrintStream(new FileOutputStream("a.txt"));
// 只要将两个资源放在try后的圆括号内即可
try (br; ps) {
// 使用两个资源
System.out.println(br.readLine());
ps.println("庄生晓梦迷蝴蝶");
}
}
}

可以看到,相较于java7try后面的括号更加精简了,看起来更加舒服。

总结

  • java7开始支持自动关闭资源
  • java7需要在try后的括号里创建需要自动关闭的资源。
  • java9只需要将需要自动关闭的资源的引用变量放到try后面的括号里即可。