java7引入try-with-resource语法,允许在try代码块声明一个或多个资源,可以确保代码块执行完毕资源被关闭。

1.使用try-catch-finally

在java7之前,我们需要在finally代码块来关闭资源,确保程序即使在try发生异常,资源也能正确的被关闭。

以下的例子,从硬盘中读取文件file.txt的内容,输出至控制台。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Test
public void testTryCatchFinally() {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(new File("D://Resource/file.txt")));
String line;
while((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

2.使用try-with-resource替代

从java7开始,你可以使用try-with-resource来替代try-catch-finally,简化代码。资源对象需要在try代码块中被声明和初始化,这样资源就会被自动的关闭。

try-with-resource语法使用的时候需要注意以下几点:

  • try()代码块中可以声明一个或多个resource(resource是指那些实现了java.lang.AutoCloseable或java.io.Closeable的对象),多个资源用分号分割
  • try-with-resource语法会自动处理资源的关闭,资源关闭的顺序跟声明的顺序相反
1
2
3
4
5
6
7
8
9
10
11
@Test
public void testTryWithResource() {
try(BufferedReader br = new BufferedReader(new FileReader(new File("D://Resource/file.txt")))) {
String line;
while((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}

3.从字节码查看try-with-resource

使用jd-gui查看方法testTryWithResource生成的字节码,可以看到try-with-resource主要做了一下2点处理

  • finally代码块中执行了资源的关闭
  • 如果在try代码块和finally代码块中都发生了异常,则会抛出try代码块捕获的异常,并抑制了finally代码块中异常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Test
public void testTryWithResource() {
try {
BufferedReader br = new BufferedReader(new FileReader(new File("D://Resource/file.txt")));Throwable localThrowable3 = null;
try {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (Throwable localThrowable1) {
localThrowable3 = localThrowable1;throw localThrowable1;
} finally {
if (br != null) {
if (localThrowable3 != null) {
try {
br.close();
} catch (Throwable localThrowable2) {
localThrowable3.addSuppressed(localThrowable2);
}
} else {
br.close();
}
}
}
}
catch (IOException e) {
e.printStackTrace();
}
}

参考链接: