返回介绍

9.6.1 用 finally 做什么

发布于 2024-10-15 23:56:22 字数 2884 浏览 0 评论 0 收藏 0

在没有“垃圾收集”以及“自动调用破坏器”机制的一种语言中(注释⑤),finally 显得特别重要,因为程序员可用它担保内存的正确释放——无论在 try 块内部发生了什么状况。但 Java 提供了垃圾收集机制,所以内存的释放几乎绝对不会成为问题。另外,它也没有构建器可供调用。既然如此,Java 里何时才会用到 finally 呢?

⑤:“破坏器”(Destructor)是“构建器”(Constructor)的反义词。它代表一个特殊的函数,一旦某个对象失去用处,通常就会调用它。我们肯定知道在哪里以及何时调用破坏器。C++提供了自动的破坏器调用机制,但 Delphi 的 Object Pascal 版本 1 及 2 却不具备这一能力(在这种语言中,破坏器的含义与用法都发生了变化)。

除将内存设回原始状态以外,若要设置另一些东西,finally 就是必需的。例如,我们有时需要打开一个文件或者建立一个网络连接,或者在屏幕上画一些东西,甚至设置外部世界的一个开关,等等。如下例所示:

//: OnOffSwitch.java
// Why use finally?

class Switch {
  boolean state = false;
  boolean read() { return state; }
  void on() { state = true; }
  void off() { state = false; }
}

public class OnOffSwitch {
  static Switch sw = new Switch();
  public static void main(String[] args) {
    try {
      sw.on();
      // Code that can throw exceptions...
      sw.off();
    } catch(NullPointerException e) {
      System.out.println("NullPointerException");
      sw.off();
    } catch(IllegalArgumentException e) {
      System.out.println("IOException");
      sw.off();
    }
  }
} ///:~

这里的目标是保证 main() 完成时开关处于关闭状态,所以将 sw.off() 置于 try 块以及每个违例控制器的末尾。但产生的一个违例有可能不是在这里捕获的,这便会错过 sw.off()。然而,利用 finally,我们可以将来自 try 块的关闭代码只置于一个地方:

//: WithFinally.java
// Finally Guarantees cleanup

class Switch2 {
  boolean state = false;
  boolean read() { return state; }
  void on() { state = true; }
  void off() { state = false; }
}

public class WithFinally {
  static Switch2 sw = new Switch2();
  public static void main(String[] args) {
    try {
      sw.on();
      // Code that can throw exceptions...
    } catch(NullPointerException e) {
      System.out.println("NullPointerException");
    } catch(IllegalArgumentException e) {
      System.out.println("IOException");
    } finally {
      sw.off();
    }
  }
} ///:~

在这儿,sw.off() 已移至一个地方。无论发生什么事情,都肯定会运行它。

即使违例不在当前的 catch 从句集里捕获,finally 都会在违例控制机制转到更高级别搜索一个控制器之前得以执行。如下所示:

//: AlwaysFinally.java
// Finally is always executed

class Ex extends Exception {}

public class AlwaysFinally {
  public static void main(String[] args) {
    System.out.println(
      "Entering first try block");
    try {
      System.out.println(
        "Entering second try block");
      try {
        throw new Ex();
      } finally {
        System.out.println(
          "finally in 2nd try block");
      }
    } catch(Ex e) {
      System.out.println(
        "Caught Ex in first try block");
    } finally {
      System.out.println(
        "finally in 1st try block");
    }
  }
} ///:~

该程序的输出展示了具体发生的事情:

Entering first try block
Entering second try block
finally in 2nd try block
Caught Ex in first try block
finally in 1st try block

若调用了 break 和 continue 语句,finally 语句也会得以执行。请注意,与作上标签的 break 和 continue 一道,finally 排除了 Java 对 goto 跳转语句的需求。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文