为什么我们使用finally块?


91

据我所知,以下两个代码段将达到相同的目的。为什么要finally块呢?

代码A:

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

代码B:

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

这不是特定于C#的问题
而是

1
java7不再需要:AutomaticResourceManagement,try(new resourceDeclartion()){}
Kanagavelu Sugumar 2014年

Answers:


139
  • 如果您未处理的异常被抛出会怎样?(我希望你不会抓到Throwable...)
  • 如果从try块内部返回会怎样?
  • 如果catch块引发异常会怎样?

一个代码finally块确保无论您退出该代码块(以几种方式明确地中止整个过程),该代码块都将被执行。这对于确定性清除资源很重要。


48
不一定正确;如果(1)有一个System.exit()调用(2)在try或catch块之一中存在无限循环,则最终将不会执行(3)我拔下计算机的插头
NullUserException 2010年

2
@Alon try {返回1;}最终{重播2;}您将获得2
Dennis C

19
@NullUserException:因此,“取模一些方法...”位
Jon Skeet 2010年

2
John Skeet生活在stackoverflow上,每个问题都像门铃响了,他必须回答:)
naikus 2010年

1
这篇文章讨论了最终不会被调用的(罕见)条件。
坎达米尔'17

13

请注意(至少在Java中,也可能在C#中),也可以有一个try不带catch,但带一个的块finally。当try块中发生异常时,将在finally更高级别抛出异常之前运行块中的代码:

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

7

无论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();
}

1
如果我不使用“ finally”,而是关闭连接怎么办?
Istiaque Ahmed

5

最终总是执行,因为捕获之后的代码可能不会执行。


1
为什么不!如果正确处理了异常,则代码将得到明确执行。
Mohammad Nadeem

1
@Nadeem:请查看我的答案,原因可能有三个。
乔恩·斯基特

2

即使我们的应用程序被强制关闭,但是如果您将这些代码行写在 finally块中无论是否抛出异常或异常,它都将执行。不...

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

在某些情况下,finally例如JVM Fail,Thread终止等将无法执行。


1

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


0

有时候,无论如何,您都希望执行一段代码。是否引发异常。然后使用finally



0

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


0

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


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


0

仍在向下滚动?干得好!

这个问题使我有些困难。

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-无论是什么

显然,当您捕获异常并将其再次抛出到其他层(漏斗)时,抛出后的代码将不会执行。它的行为类似于函数内部返回的工作方式。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.