Java中的Try with Resources语句介绍
1.介绍
从Java7诞生了try-with-resources,这家伙可以在资源使用完后实现自动关闭回收。想想我们之前打开一个文件或流对象用完咋整的,是不是finally语句块中手动close的。
当然这类可自动关闭的资源前提是必须实现了AutoCloseable接口。
2.如何使用?
拿PrintWriter对象举例,资源必须在try结构中声明和初始化:
try (PrintWriter writer = new PrintWriter(new File("test.txt"))) {
writer.println("Hello World");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
看下JDK1.8中PrintWriter的定义:
All Implemented Interfaces:
Closeable, Flushable, Appendable, AutoCloseable
3.使用try-with-resources替代try-catch-finally
Scanner scanner = null;
try {
scanner = new Scanner(new File("test.txt"));
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (scanner != null) {
scanner.close();
}
}
- 下面是try-resources
try (Scanner scanner = new Scanner(new File("test.txt"))) {
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
}
4.同时使用多个资源
可以在一个try-with-resources块中用分号分隔以声明多个资源。例如:
try (Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
while (scanner.hasNext()) {
writer.print(scanner.nextLine());
}
}
5.自定义一个实现了AutoCloseable接口的资源
前提是要实现Closeable或AutoCloseable接口,同时重写close方法。例如:
public class MyResource implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println("Closed MyResource");
}
}
6.资源的关闭顺序是怎样的?
这里遵循的是:最先被定义/获取的资源最后被关闭。以下为例:
- 资源1
public class AutoCloseableResourcesFirst implements AutoCloseable {
public AutoCloseableResourcesFirst() {
System.out.println("Constructor -> AutoCloseableResources_First");
}
public void doSomething() {
System.out.println("Something -> AutoCloseableResources_First");
}
@Override
public void close() throws Exception {
System.out.println("Closed AutoCloseableResources_First");
}
}
- 资源2
public class AutoCloseableResourcesSecond implements AutoCloseable {
public AutoCloseableResourcesSecond() {
System.out.println("Constructor -> AutoCloseableResources_Second");
}
public void doSomething() {
System.out.println("Something -> AutoCloseableResources_Second");
}
@Override
public void close() throws Exception {
System.out.println("Closed AutoCloseableResources_Second");
}
}
- 测试
private void orderOfClosingResources() throws Exception {
try (AutoCloseableResourcesFirst af = new AutoCloseableResourcesFirst();
AutoCloseableResourcesSecond as = new AutoCloseableResourcesSecond()) {
af.doSomething();
as.doSomething();
}
}
输出:
Constructor -> AutoCloseableResources_First
Constructor -> AutoCloseableResources_Second
Something -> AutoCloseableResources_First
Something -> AutoCloseableResources_Second
Closed AutoCloseableResources_Second
Closed AutoCloseableResources_First
7.Java9中的改进
来到java9我们可以在try-with-resources块中使用final或effectively final变量:
final Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))
try (scanner;writer) {
// omitted
}
如上,scanner变量声明为final,而writer变量没有显式声明final,但是很明显它在第一次赋值后并没有做其它改变,java8开始自动认为其为final变量。这一特性也就是effectively final。