【问题标题】:Why do we use finally blocks? [duplicate]为什么我们使用 finally 块? [复制]
【发布时间】:2010-08-06 06:33:43
【问题描述】:

据我所知,以下两个代码 sn-ps 将用于相同的目的。为什么有 finally 块?

代码 A:

try { /* Some code */ }
catch { /* Exception handling code */ }
finally { /* Cleanup code */ }

代码 B:

try { /* Some code */ }
catch { /* Exception handling code */ }
// Cleanup code

【问题讨论】:

  • 这不是特定于 C# 它是一个 .Net 问题
  • java7 不再需要:AutomaticResourceManagement, try(new resourceDeclartion()){}

标签: java .net finally


【解决方案1】:
  • 如果抛出您未处理的异常会怎样? (我希望你没有看到 Throwable...)
  • 如果从 try 块内返回会发生什么?
  • 如果 catch 块抛出异常会怎样?

finally 块确保无论如何您退出该块(以几种显式中止整个过程的方式为模),它将被执行。这对于资源的确定性清理很重要。

【讨论】:

  • 不一定正确;如果 (1) 有一个 System.exit() 调用 (2) 在 try 或其中一个 catch 块中有一个无限循环 (3) 我拔掉了计算机上的插头,finally 将不会被执行
  • @Alon try{ return 1; }finally{ 重新运行 2; } 你会得到 2
  • @NullUserException:因此“模数几种方式......”位
  • John Skeet 住在 stackoverflow 上,每个问题都像门铃响起,他必须回答 :)
  • This post 讨论了最终不会被调用的(罕见)条件。
【解决方案2】:

请注意(至少在 Java 中,也可能在 C# 中)也可以有一个没有 catch 的 try 块,但有一个 finally。当try 块中发生异常时,finally 块中的代码会在异常向上抛出之前运行:

InputStream in = new FileInputStream("somefile.xyz");
try {
    somethingThatMightThrowAnException();
}
finally {
    // cleanup here
    in.close();
}

【讨论】:

    【解决方案3】:

    您可能想要放置您想要执行的代码,而不管您的 try 或 catch 块中发生什么。

    此外,如果您使用多个 catch 并且如果您想放置一些对于所有 catch 块都通用的代码,这将是一个放置的地方 - 但您不能确定 try 中的整个代码是否已执行。

    例如:

    conn c1 = new connection();
    try {
        c1.dosomething();
    } catch (ExceptionA exa) {
        handleexA();
        //c1.close();
    } catch (ExceptionB exb) {
        handleexB();
        //c1.close();
    } finally {
        c1.close();
    }
    

    【讨论】:

    • 如果我不使用'finally'而是关闭连接怎么办?
    【解决方案4】:

    最后总是被执行,而你的代码在 catch 之后可能不会。

    【讨论】:

    • 为什么不呢!如果异常处理得当,代码将被明确执行。
    • @Nadeem:请参阅我的回答,因为 3 个原因可能不会发生。
    【解决方案5】:

    即使我们的应用程序被强制关闭,也会有一些我们必须执行的任务(如内存释放、关闭数据库、释放锁等),如果你在finally 块中编写这些代码行,它将执行是否抛出异常...

    您的应用程序可能是线程的集合,Exception 终止线程而不是整个应用程序,在这种情况下finally 更有用。

    在某些情况下finally 不会执行,例如 JVM Fail、线程终止等。

    【讨论】:

      【解决方案6】:

      因为无论可能引发任何异常,您都需要执行该代码。例如,您可能需要清理一些非托管资源('using' 构造编译为 try/finally 块)。

      【讨论】:

        【解决方案7】:

        仍在向下滚动?给你!

        这个问题让我回想起了一段艰难的时光。

        try
        {
         int a=1;
         int b=0;
         int c=a/b;
        }
        catch(Exception ex)
        {
         console.writeline(ex.Message);
        }
        finally
        {
         console.writeline("Finally block");
        }
        console.writeline("After finally");
        

        在上述场景中会打印什么? 是的,没猜错:

        • ex.Message——不管它是什么(可能试图除以零)

        • 终于封杀

        • 终于

          try
          {
              int a=1;
              int b=0;
              int c=a/b;
          }
          catch(Exception ex)
          {
              throw(ex);
          }
          finally
          {
              console.writeline("Finally block");
          }
          console.writeline("After finally");
          

        这会打印什么?没有!由于 catch 块引发错误,因此引发错误。

        在良好的编程结构中,您的异常将被汇集,即此代码将从另一层处理。为了刺激这种情况,我将嵌套尝试此代码。

        try
        {    
         try
            {
             int a=1;
             int b=0;
             int c=a/b;
            }
            catch(Exception ex)
            {
             throw(ex);
            }
            finally
            {
             console.writeline("Finally block")
            }
            console.writeline("After finally");
        }
        catch(Exception ex)
        {
         console.writeline(ex.Message);
        }
        

        在这种情况下,输出将是:

        • 终于屏蔽了
        • ex.Message——不管它是什么。

        很明显,当你捕获一个异常并再次将其抛出到其他层(Funneling)时,抛出后的代码不会被执行。它的作用类似于函数内部的 return 工作方式。

        您现在知道为什么不在 catch 块之后关闭代码上的资源了。将它们放在 finally 块中。

        【讨论】:

          【解决方案8】:

          有时您可能无论如何都想执行一段代码。是否抛出异常。然后使用finally。

          【讨论】:

            【解决方案9】:

            finally 总是执行,除非 JVM 被关闭,finally 只是提供了一种将清理代码放在一个地方的方法。

            如果您必须将清理代码放在每个 catch 块中,那就太乏味了。

            【讨论】:

              【解决方案10】:

              如果 catch 块抛出任何异常,那么剩余的代码将不会执行,因此我们必须编写 finaly 块。

              【讨论】:

                【解决方案11】:

                java中的finally块可用于放置“清理”代码,例如关闭文件、关闭连接等。


                如果程序退出(通过调用 System.exit() 或通过导致导致进程中止的致命错误),将不会执行 finally 块。

                【讨论】:

                  猜你喜欢
                  • 2016-02-04
                  • 2015-05-17
                  • 2020-01-29
                  • 2019-12-07
                  • 1970-01-01
                  • 2017-12-06
                  • 1970-01-01
                  • 2018-12-28
                  • 2019-08-10
                  相关资源
                  最近更新 更多