15

我用try-catch了很多年,但我从来没有学会如何以及何时使用finally,因为我从来不明白finally(我读过坏书)的意义何在?

我想问你关于finally我的情况的使用。

我的代码示例应该解释一切:

$s = "";

$c = MyClassForFileHandling::getInstance();

try
{
    $s = $c->get_file_content($path);
}

catch FileNotFoundExeption
{
    $c->create_file($path, "text for new file");
}

finally
{
    $s = $c->get_file_content($path);
}

这是finally的正确使用吗?

更精确的问题:

我应该使用finally(在未来的 PHP 版本或其他语言中)来处理“如果不存在就创建”操作吗?

4

4 回答 4

31

finally 将始终被执行,因此在这种情况下,这不是它的预期目的,因为正常执行会再次重新打开文件。如果您这样做,您打算做的事情将以相同(更清洁)的方式实现

$s = "";

$c = MyClassForFileHandling::getInstance();

try
{
    $s = $c->get_file_content($path);
}
catch(FileNotFoundExeption $e)
{
    $c->create_file($path, "text for new file");
    $s = $c->get_file_content($path);
}

然后手册说:

对于之前没有遇到 finally 块的人来说,它们与 try/catch 块之后的普通代码之间的主要区别在于,即使 try/catch 块会将控制权返回给调用函数,它们也会被执行。

如果出现以下情况,它可能会这样做:

  • 如果您的 try 块包含您未捕获的异常类型,则代码
  • 你在你的 catch 块中抛出另一个异常
  • 您的 try 或 catch 块调用返回

finally 在这种情况下很有用:

function my_get_file_content($path)
{
    try
    {
        return $c->get_file_content($path);
    }
    catch(FileNotFoundExeption $e)
    {
        $c->create_file($path, "text for new file");
        return $c->get_file_content($path);
    }
    finally
    {
        $c->close_file_handler();
    }
}

=> 如果您需要确保在这种情况下关闭文件处理程序,或者一般情况下关闭某些资源。

于 2013-02-22T19:32:34.543 回答
4

finally直到 5.5 版才被引入 PHP,该版本还没有发布,所以你还没有看到任何例子。因此,除非您正在运行 PHP 5.5 的 alpha 版本,否则您还不能使用finally

来自手册(例外

在 PHP 5.5 及更高版本中,也可以在 catch 块之后指定 finally 块。finally 块中的代码将始终在 try 和 catch 块之后执行,无论是否引发了异常,并且在正常执行恢复之前。

使用手册中的示例finally

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    else return 1/$x;
}

try {
    echo inverse(5) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
} finally {
    echo "First finally.\n";
}

try {
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
} finally {
    echo "Second finally.\n";
}

// Continue execution
echo 'Hello World';
?>
于 2013-02-22T19:11:58.697 回答
0

finally 表示你最后想要做什么。

try
{
    $s = $c->get_file_content($path);
}

catch FileNotFoundExeption
{
    $c->create_file($path, "text for new file");
}

finally
{
    //Create a pdf with my file
    //or, Rename my file
    //or, store my file into Database
}

无论在 try 或 catch 中发生什么(无论是否引发了异常),“最终代码”都会执行。所以,没有必要在“try”和“finally”上使用相同的代码。这是否简单地回答了您的问题?

于 2013-02-22T19:13:26.563 回答
0

我只想指定,如果块中发生异常,try即使存在块,异常也会正确引发finally。块的用处finally是干净和免费的资源。我认为最好的用途是,例如,当您上传文件但随后发生错误时:

$tmp_name = null;
try {
    $tmp_name = tempnam(UPLOAD_DIR, 'prefix');
    move_uploaded_file($file['tmp_name'], $tmp_name);
    ImageManager::resize($tmp_name, $real_path, $width, $height); // this will rise some exception
}
finally {
    if($tmp_name)
        unlink($tmp_name); // this will ensure the temp file is ALWAYS deleted
}

如您所见,这样无论发生什么情况,临时文件都会被正确删除。
如果我们要finally在旧版本的 PHP 中模拟该子句,我们应该这样写:

// start finally
catch(Exception $ex) {
}
if($tmp_name)
    unlink($tmp_name);
if( isset($ex) )
    throw $ex;
// end finally

catch请注意,如果块捕获了某些东西,则会重新抛出异常。它与版本不清楚finally,但工作方式相同。

于 2014-11-30T17:17:44.313 回答