原文: https://howtodoinjava.com/java7/try-with-resources/

Java 7 为懒惰的 Java 开发人员带来了一些非常好的特性。try-with-resource是这样的特性之一,它可以减少代码行,并使代码更健壮。 在本教程中,我将讨论有关此特性的内容。

Java 7 中的`try-with-resources` - 图1

  1. Sections in this post:
  2. The old way of resource cleanup (Before java 7)
  3. The new fancy way with try-with-resources (syntax example)
  4. How actually it works?
  5. Adding functionality to custom resources
  6. Final notes

资源清除的旧方法(在 Java 7 之前)

我们长期以来一直在这样做。 例如从文件系统读取文件。 代码可能看起来有所不同,但流程如下例所示:

  1. public class ResourceManagementBeforeJava7
  2. {
  3. public static void main(String[] args)
  4. {
  5. BufferedReader br = null;
  6. try
  7. {
  8. String sCurrentLine;
  9. br = new BufferedReader(new FileReader("C:/temp/test.txt"));
  10. while ((sCurrentLine = br.readLine()) != null)
  11. {
  12. System.out.println(sCurrentLine);
  13. }
  14. }
  15. catch (IOException e)
  16. {
  17. e.printStackTrace();
  18. }
  19. finally
  20. {
  21. try
  22. {
  23. if (br != null)
  24. br.close();
  25. }
  26. catch (IOException ex) {
  27. ex.printStackTrace();
  28. }
  29. }
  30. }
  31. }

这些类型的代码在具有大量 IO 操作的应用程序代码库中非常常见。

trycatch块中的代码本质上很重要,并且具有一些特定于应用程序的逻辑。 但是,finally块呢? 在大多数情况下,最后只是复制粘贴了finally块,目的是通过关闭它们来避免损坏资源。

当您有 3-4 个这样的资源要在单个finally块中关闭时,这些finally块看起来更难看。 当我们知道时,您是否认为这些finally块不必要地存在,我们必须以任何方式关闭资源而没有任何异常情况?

Java 7 通过try-with-resources特性解决了这个问题。

使用try-with-resources的新方法(语法示例)

现在看看在 Java 7 中打开和关闭资源的新方法。

  1. public class ResourceManagementInJava7
  2. {
  3. public static void main(String[] args)
  4. {
  5. try (BufferedReader br = new BufferedReader(new FileReader("C:/temp/test.txt")))
  6. {
  7. String sCurrentLine;
  8. while ((sCurrentLine = br.readLine()) != null)
  9. {
  10. System.out.println(sCurrentLine);
  11. }
  12. }
  13. catch (IOException e)
  14. {
  15. e.printStackTrace();
  16. }
  17. }
  18. }

有两件事需要密切注意:

  1. 文件资源(BufferedReader)以特殊方式在try块中打开(在小括号内)。
  2. finally块完全消失了。

最后但并非最不重要的一点是,代码看起来很漂亮且易于阅读。 很好,对吗? 但是实际上是如何工作的?

实际上如何运作?

在 Java 7 中,我们有一个新的超接口java.lang.AutoCloseable。 此接口有一种方法:

  1. void close() throws Exception;

Java 文档建议将此接口实现在不再需要它时必须关闭的任何资源上

当我们在特殊的try-with-resource块中打开任何此类AutoCloseable资源时,在try块完成后, JVM 会对在try()中初始化的所有资源调用此close()方法。

例如,BufferedReader已实现close()方法文件如下:

  1. public void close() throws IOException {
  2. synchronized (lock) {
  3. if (in == null)
  4. return;
  5. in.close();
  6. in = null;
  7. cb = null;
  8. }
  9. }

由于上述方法定义,当 JVM 调用此方法时,所有基础流或 IO 资源都将关闭。

向自定义资源添加功能

好吧,这是一个很好的资源清理设计。 但是它仅适用于 JDK 本机类吗? 没有。 您也可以将其用于自定义资源。

例如,我在以下代码中创建了一个自定义资源:

  1. public class CustomResource implements AutoCloseable
  2. {
  3. public void accessResource() {
  4. System.out.println("Accessing the resource");
  5. }
  6. @Override
  7. public void close() throws Exception {
  8. System.out.println("CustomResource closed automatically");
  9. }
  10. }

现在,我将在示例代码中使用它:

  1. public class TryWithCustomResource
  2. {
  3. public static void main(String[] args)
  4. {
  5. try(CustomResource cr = new CustomResource())
  6. {
  7. cr.accessResource();
  8. }
  9. catch (Exception e)
  10. {
  11. e.printStackTrace();
  12. }
  13. }
  14. }
  15. Putput in console:
  16. Accessing the resource
  17. CustomResource closed automatically

控制台中的输出清楚地证明,try块完成后,资源将自动关闭。

最后注意事项

这就是 Java 7 中使用try-with-resources进行自动资源管理的全部内容。让我们逐点记下重点:

  • 在 Java 7 之前,我们必须使用finally块来清理资源。 finally块不是强制性的,但是清理资源是为了防止系统损坏。
  • 使用 Java 7,无需显式的资源清理。 它是自动完成的。
  • try-with-resources块(try(…){…})中初始化资源时完成自动资源清理。
  • 由于新接口AutoCloseable而发生清除。 try块完成后,JVM 将立即调用其close方法。
  • 如果要在自定义资源中使用此特性,则必须实现AutoCloseable接口。 否则程序将无法编译。
  • 您不应在代码中调用close()方法。 这应该自动称为 JVM。 手动调用它可能会导致意外结果。

祝您学习愉快!