【问题标题】:When to use try finally and not try catch finally [duplicate]何时使用 try finally 而不是 try catch finally [重复]
【发布时间】:2013-04-03 18:47:21
【问题描述】:

使用 Try Catch finally 块的最佳做法是什么?你喜欢只使用 try finally 块而不是 try catch 块吗?我一直认为 try catch finally 是最好的做法。但是,在我正在使用的部分代码中,我看到了这样的代码:

试试{ 做点什么(); } 最后{ doSomethingElse(); }

由于他们没有捕捉到异常,我很难调试代码。不使用 catch 并且只使用 finally 对我来说不是一个很好的做法,但我可能错了。

据我所知,这并不是一个好的做法。基本上,我们没有使用 try catch 的用途。我也发现了类似的questions

我的问题是:“您是否同意我对以下假设的看法:最佳实践是一起使用 try catch finally 而不是 try finally。”如果您不同意,请您提供一个示例,说明何时使用 try finally 而不是 try catch finally,以及为什么您认为 try finally 比 try catch 更好?

【问题讨论】:

  • @Perception 我在最初的问题中提到了这一点。这对我来说并不重复,因为他没有直接询问何时使用 try finally 块。我可能错了。
  • 这几乎就是其他问题作者在问“正在使用 try/finally 而没有捕获反模式”时的意思。在这种情况下,反模式是一种不应该遵循的做法(也不是最好的)。您的问题是必不可少的重复。

标签: java exception try-catch


【解决方案1】:

我不同意,如果你不能对抛出的异常做任何事情,但调用者层次结构可以做一些事情,那么使用 finally 来清理你的资源,并让调用者在抛出异常后处理清理。

【讨论】:

  • 在这种情况下,你会有一个 catch 向调用函数抛出一个新的异常,不是吗?
  • 这完全正确。有时您可能无法处理异常,或者不想这样做,但您确实希望确保错误不会导致您的资源保持打开状态,从而影响后续运行的性能。在这种情况下,try-finally 非常好。
  • @75inchpianist 何必呢?正如我所说,您无能为力来处理这种情况,所以让异常渗透直到它可以被处理,但这并不能原谅更接近异常的代码处理清理资源。在发生这种情况的代码中,我通常会记录我期望抛出的内容以及何时减少混淆。
  • @75inchpianist,没有。如果抛出异常,它将被抛出堆栈,直到有东西处理它。它不会在尝试中“消失”{}finally{},因为没有任何东西能捕捉到它
  • @sheidaei 是的,这正是它的工作原理。除非你的 finally 代码抛出异常,如果发生这种情况,那么原始异常就会被抑制,在我看来,finally 块永远不应该被允许抛出异常(但它们应该记录它们)。
【解决方案2】:

finally 构造的目的是提供始终执行的代码,即使抛出异常也是如此。

try / finally(无捕获)允许您编写保证执行的代码,即使 try 块内的代码抛出运行时异常也是如此。

这在您使用的代码可能会引发运行时异常但不会引发已检查异常的情况下非常有用。一个例子是 Spring DAO 支持;它将 IOExceptions 包装在运行时异常中。

【讨论】:

  • 这是一个很好的观点。但是,我认为既然你有一个 try finally 块,为什么不让它成为一个 try catch finally 块。在 catch 块中,捕获最常见的异常,将其记录下来,如果您不想处理它,则将其抛出。这样,如果您遇到问题,您可以轻松检查哪里出错了。我错过了什么吗?
  • 我可能不知道第 3 方代码抛出了什么 RuntimeExceptions。 try/finally 允许我关闭我的资源并避免使用 catch(Exception blammy) 块。
【解决方案3】:

通常 try-finally 用于确保执行某些代码,而不管是否发生异常。 通常缺少 Catch 块,因为 try 块中的代码不会抛出任何可以捕获的已检查异常。

例如:

try  {

        if(str.length() > 0) { // If str is null, it can throw NullPointer and hence code below it wont execute
            // some code
        }

    }finally {
        // Will be performed even if any unchecked exception is thrown
        // Must contain code which has to be performed at any cost like releasing occupied memory
    }

【讨论】:

  • 这是一个很好的观点。但是,我认为既然你有一个 try finally 块,为什么不让它成为一个 try catch finally 块。在 catch 块中,捕获最常见的异常,将其记录下来,如果您不想处理它,则将其抛出。这样,如果您遇到问题,您可以轻松检查哪里出错了。我错过了什么吗?
【解决方案4】:

共有三种可能,try+catch、try+finally 或 try+catch+finally。它们都有自己的用途。

当您可以做一些有用的事情来处理异常时,将 catch 与 try 一起使用,例如报告发生异常的事实。

finally 块中的代码始终运行,与是否发生异常无关,因此在需要清理时将 finally 与 try 一起使用,这总是必须发生的。如果文件已成功打开,则以关闭文件为例。

【讨论】:

  • 所以,如果我不能对异常做任何事情,那么捕获异常,对其进行处理(至少记录它)然后抛出异常不是更好的做法吗?
  • 你当然可以这样做,但对我来说这不是最佳做法。一方面,这意味着同一个异常可能会被记录多次,在调用堆栈展开时在每个 catch 块中记录一次。我认为将异常记录在最高级别并使用 StackTrace 方法来确定和记录异常发生的位置更有意义。如果您无法处理异常,这还具有保持代码更小的优点。
  • @Stochasticly:虽然在显示日志时通常应该抑制重复的日志条目,但在尝试追踪异常似乎“消失”的情况时,它们有时会很有用。我不喜欢一般原则上的 catch-and-rethrow(应该有一个“错误”块,它不会假装处理异常),但在调用堆栈中记录异常的进度似乎是个好主意。
【解决方案5】:

我不同意。

try{}finally{} 应用于无法处理异常但需要清理资源的情况。

try{}finally{} 块不会像您想象的那样导致异常“消失”。它将被抛出堆栈并在其他地方处理。如果您在当前应用程序中看不到异常,那是因为它被其他地方丢弃了。

try {
    connection = createConnection();
}
finally {
    closeConnection(connection) //Free database connection.
}

在这种情况下,您可能无法处理 SQL 异常,但您仍想释放数据库连接。

【讨论】:

  • 你不认为最好有一个catch块来捕获异常,至少记录情况然后再次抛出它吗?
  • @sheidaei,没有。这样做是一种反模式,并且会导致每个异常记录十多次的日志。异常将被抛出链并最终记录。可能由虚拟机提供。
猜你喜欢
  • 2014-11-27
  • 2018-10-24
  • 2013-02-19
  • 2016-03-28
  • 2010-11-25
  • 1970-01-01
  • 1970-01-01
  • 2011-02-20
  • 2019-02-28
相关资源
最近更新 更多