finally 块中的异常

Posted

技术标签:

【中文标题】finally 块中的异常【英文标题】:Exception in finally block 【发布时间】:2018-03-18 03:41:01 【问题描述】:

如果 finally 代码块中引发了异常,finally 块的其余部分是否执行?

try
  statementList1
finally
  command;
  command_that_raises;
  critical_command;
end

critical_command 会被执行吗?

Manual 只讨论异常,不讨论代码执行:

如果引发了异常但未在 finally 子句中处理,则该异常会从 try...finally 语句中传播出去,并且任何已在 try 子句中引发的异常都会丢失。因此 finally 子句应该处理所有本地引发的异常,以免干扰其他异常的传播。

【问题讨论】:

您引用的手册部分肯定与您的问题有关,因为您要询问 如果在 finally 代码块中引发了 异常...。所以我不知道你为什么认为它不适用。由于执行导致此类异常的代码而发生异常。根据手册,如果command_that_raises 导致异常,那么除非您在finally 块内处理它,否则您将丢失当前异常并且不会执行critical_command。就像手册说的那样。 好吧,我想,由于 finally 块是保证执行的,所以所有行都被强制逐行执行。我猜我错了。 这就是为什么你通常会在 finally 块中看到,只有不能引发的代码。 难道你不能在大约两分钟内在一个包含大约 10 行代码的快速控制台应用程序中解决这个问题吗?在跑去发布一个需要更长时间编写、格式化和发布的问题之前,实际上试图通过一些实验自己回答问题的人发生了什么? 可能是因为它很容易测试,结果也很容易解释,之前没人愿意讨论它...... 【参考方案1】:

查看以下确认:

procedure TForm6.Button1Click(Sender: TObject);
begin

  try
    ShowMessage('begin');
  finally
    ShowMessage('enter');
    raise Exception.Create('raise');
    ShowMessage('end');
  end;

end;

现在对于这个案例:

procedure RaiseAndContinue;
begin
  try
    raise Exception.Create('raise');
  except

  end;
end;

procedure TForm6.Button1Click(Sender: TObject);
begin

  try
    ShowMessage('begin');
  finally
    ShowMessage('enter');
    RaiseAndContinue;
    ShowMessage('end');
  end;

end;

简短的回答是:除非您处理该异常,否则代码将不会被执行。

【讨论】:

以上是关于finally 块中的异常的主要内容,如果未能解决你的问题,请参考以下文章

在 finally 块中抛出异常

finally中流关闭失败需要抛出异常吗

finally回收资源

如果在 catch 块中抛出异常,是不是会执行 finally 块? [复制]

JAVA09异常处理之动手动脑问题

Java中,finally在try语句块中的return前执行还是后执行