try-with-resources 在 Java 开发中的实践

概述

本文介绍 try-with-resources 的使用以及带来的好处

try-with-resources 概念

在实际项目开发为了避免资源泄漏,最好的做法是在 finally 块中关闭资源对象(如 FileOutputStream 等)。

原因是 finally 块即使在出现异常时也会被执行

但是不要在 try 语句中关闭资源,因为当 try 块中的语句抛出异常或者自己实现的代码抛出异常,那么就不会执行最后的关闭语句,从而资源也无法释放。

与在 finally 块中关闭资源不同,try-with-resources 只是一个语法糖,用于关闭任何资源类(实现了 AutoCloseable )对象(在 Java1.7 中引入),

try-with-resources 相比 try–catch-finally 来说不需要手动去关闭资源,只要根据约定实现了 AutoCloseable 接口,就会自动调用 close 方法。

关键点

  1. try 圆括号中的资源必须实现 AutoCloseable 接口
  2. try-with-resources 是在 Java1.7 中引入的
  3. 不要在 try 语句中做关闭资源的操作

举例说明

try–catch-finally 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
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-with-resources 实现

1
2
3
4
5
6
7
try (Scanner scanner = new Scanner(new File("test.txt"))) {
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
}

也可以支持多行,具体如下

1
2
3
4
5
6
7
8
try (Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {

while (scanner.hasNext()) {
writer.print(scanner.nextLine());
}

}

try-with-resources 解决的问题

  1. try-with-resources 明确了需要关闭资源的对象,这些对象必须实现 AutoCloseable 对象
  2. 相对于 try-catch-finally 来说简化了代码,try-with-resources 不需要在 finally 代码库中调用 close 方法

try-with-resources 中的资源关闭顺序

这里通过一个例子来测试一下

  1. 实现了 AutoCloseable 接口的 MyAutoClose1 和 MyAutoClose2 如下
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
public class MyAutoClose1 implements AutoCloseable {

private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

public void work() {
logger.info("work");
}

@Override
public void close() throws Exception {
logger.info("close");
}
}

public class MyAutoClose2 implements AutoCloseable {

private static final Logger logger =
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

public void work() {
logger.info("work");
}

@Override
public void close() throws Exception {
logger.info("close");
}
}
  1. 测试代码如下
1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void test1() {
try (
final MyAutoClose1 myAutoClose1 = new MyAutoClose1();
final MyAutoClose2 myAutoClose2 = new MyAutoClose2();
) {
myAutoClose1.work();
myAutoClose2.work();
} catch (final Exception e) {
e.printStackTrace();
}
}
  1. 执行如下
1
2
3
4
19:51:06.755 [main] INFO  c.c.xutils.test.trys.MyAutoClose1 - work
19:51:06.758 [main] INFO c.c.xutils.test.trys.MyAutoClose2 - work
19:51:06.758 [main] INFO c.c.xutils.test.trys.MyAutoClose2 - close
19:51:06.758 [main] INFO c.c.xutils.test.trys.MyAutoClose1 - close

参考

打赏

  • 微信

  • 支付宝