Java 9:改进的Try-With-Resources

时间:2021-12-20 16:25:10

Java 7之前

在Java 7之前,在使用一些资源的类时,如BufferedReader,我们要常常提醒自己,必须要在finally块关闭资源。

Java 6示例

BufferedReader br = null;
try {
  br = new BufferedReader(new FileReader("C:\\test.txt"));
  System.out.println(br.readLine());
} catch (IOException e) {
  e.printStackTrace();
} finally {
  try {
    if (br != null)
      br.close();
  } catch (IOException ex) {
    ex.printStackTrace();
  }
}

在Java 6的这个示例里,这段代码有几点不好:

  1. 代码冗长,不可读
  2. 在finally块了还需要对close()方法添加try-catch
  3. 在调用close()前,总要判断Reader是否为null
  4. 如果忘了在finally关闭资源,容易造成资源泄漏

Java 7

Java 7新增了try-with-resoureces自动管理资源的语法。

Java 7示例

try (BufferedReader br = new BufferedReader(new FileReader("C:\\test.txt"))) {
  System.out.println(br.readLine());
} catch (IOException e) {
  e.printStackTrace();
}

这短短的几行代码很优雅地解决了Java 7之前对资源管理存在的问题。 在try()里声明的资源,用户不需要手动关闭资源,它会在用完后自动关闭。这样不需要在关闭资源时的try-catch以及检查资源是否为null,也很好避免了因为忘记关闭资源可能导致的资源泄漏。

Java 7的try-with-resources语法需要符合以下规则:

  1. 资源类需要实现java.lang.AutoCloseable接口
  2. 资源变量必须在try()声明为本地变量。
  3. 如果资源在Try-With-Resources语句外声明,那么必须在try()里使用本地变量引用外部声明的资源变量

以下例子不正确

BufferedReader br = new BufferedReader(new FileReader("C:\\test.txt"))
try (br) {
  System.out.println(br.readLine());
} catch (IOException e) {
  e.printStackTrace();
}

需要改为

BufferedReader br = new BufferedReader(new FileReader("C:\\test.txt"))
try (BufferedReader localReader = br) {   //重新引用为本地变量
  System.out.println(localReader.readLine());
} catch (IOException e) {
  e.printStackTrace();
}

这也算是Java 7/8的Try-With-Resouces bug。

Java 9

Try-With-Resouces在Java 9的改进就是针对Java7/8里资源必须在try()里声明的问题做的修改。

Java 9改进后的Try-With-Resouces允许资源在Try-With-Resouces外部声明,且不需要在try()里重新引用。

BufferedReader reader = new BufferedReader(new FileReader("test.txt"));
 try (reader) {
   System.out.println(reader.readLine());
 }