【问题标题】:Benefits of the "finally" clause in exception handling [duplicate]“finally”子句在异常处理中的好处 [重复]
【发布时间】:2013-12-13 16:49:23
【问题描述】:

作为这方面的新手,在异常处理中使用finally 子句有什么好处。或者换句话说,什么时候最好使用它,什么时候最好不要使用它。

我能想到的唯一一个就是关闭输入/输出流...任何其他好处???!!

【问题讨论】:

  • 日志,处理失败或成功都想执行的代码
  • 例如,当数据库插入/更新/删除请求失败时,这对于回滚事务非常有用。

标签: java exception exception-handling try-catch-finally finally


【解决方案1】:

finally 在需要释放某些资源的情况下非常非常有用。

例如:

InputStream is = null;
try {
    is = new FileInputStream("C://test.txt");
    //some reading-file logic 
} catch (Exception e) {
    //exception handling
} finally {
    //releasing the resources (closing the input stream)
    if (is != null) {
        is.close();
    }
}

【讨论】:

  • is = .. 应该在 try 子句中,还要检查 java7 功能 try with resources
  • 我建议在尝试关闭之前测试 is==null。
  • 另一种方式:org.apache.commons.io.IOUtils.closeQuietly(is);
  • @kocko:在第二个示例中,您实际上并没有使用 try-with-resources....
【解决方案2】:

对于任何你想在所有任务完成时执行的任务,finally 块都是有用的。在这里,我指的是最后的任务中的任何一个。释放资源、关闭流、完成自己的任何操作的结束任务等。

我们知道 finally 块总是在任何异常之后执行。所以 finally 块中的操作是有保证的。所以这些是最终应该完成的任务。

【讨论】:

    【解决方案3】:

    StinePike 写的任何东西都很完美,但我想在其中添加一些内容。

    无论是否发生异常,Finally 块都会执行......所以我们可以通过在 try 块和 catch 块()中编写 finally 块代码来实现这一点而无需 finally 块。现在如果没有发生异常,则执行try块中的代码。如果发生异常,则执行catch块中的代码。

    所以 finally 块的另一个好处是你可以在方法的任何地方写 return 语句,仍然会执行 finally 块但是如果你不在 finally 块中编写代码并从方法中返回,则不会执行代码(基于某些条件)在到达该代码之前。

    【讨论】:

    • 太棒了...但是,如果有一个异常但没有被任何 catch 子句捕获,是否有可能通过将我们的其余代码嵌入到finally 子句并完成程序....
    • @Sofiane_AbuAmir... 是的,您可以这样做。仍然 finally 块被执行,但是异常被抛出给调用者方法,因为你的任何 catch 块都没有捕获到异常。我想说你可以做很多事情,但这不是好的编程风格。
    • @Jatin Khurana ....thankx Jatin,我也这么想,但不确定。
    【解决方案4】:

    您已经想到了一个很好的例子。关闭 I/O 流,或者更一般地释放/释放您之前打开/创建的任何类型的资源。

    另一个例子可能是终止您可能已经创建的进程/线程。

    此外,您还可以向客户端组件发送事件/通知。

    【讨论】:

      【解决方案5】:

      finally 有用的另一种情况是确保释放“手动”锁(使用语言的同步结构实现的锁在内部使用finally 来实现此目的)。然而,在这样做时,有时会忽略一个细节:通常获取锁是为了允许代码暂时违反对象的不变量并在其他人注意到之前重新建立它们。如果发生异常使对象的不变量处于不正确的状态,正确的行为通常是不要让锁保持,而是确保设置一个变量以指示已经发生,并让任何获得锁的人检查这个如果设置了变量并抛出异常。

      如果将 lock-is-valid 变量封装在锁对象中,代码可能如下所示:

      void insertItem(...)
      {
        try
        {
          myLock.acquire();
          myLock.enterDanger();
          ...
          myLock.leaveDanger();
        }
        finally
        {
          myLock.release();
        }
      }
      

      永远不会修改受保护对象而只是读取它的代码永远不必“进入危险”。如果在锁仍处于danger 状态时调用release,它可能希望捕获当前堆栈跟踪;对myLock.acquire 的未决或未来调用应引发异常,可能包括该堆栈跟踪作为补充信息。

      请注意,可以尝试在catch 块中使myLock 无效,但必须确保没有人将catch 块添加到try 块以处理预期的异常而不使锁无效。如果预期的异常发生在意外的地方,则受保护的对象可能会处于损坏状态,而不会触发应该使其无效的catch(执行更具体的捕获将阻止执行不太具体的捕获) .

      【讨论】:

      • 很好的例子,我从来没想过。
      猜你喜欢
      • 1970-01-01
      • 2015-01-17
      • 1970-01-01
      • 2011-08-26
      • 2016-09-19
      • 1970-01-01
      • 2011-08-28
      • 2013-03-15
      • 1970-01-01
      相关资源
      最近更新 更多