【问题标题】:Confused by this PHP Exception try..catch nesting对此 PHP 异常感到困惑 try..catch 嵌套
【发布时间】:2011-02-04 21:48:29
【问题描述】:

我对以下代码感到困惑:

class MyException extends Exception {}
class AnotherException extends MyException {}

class Foo {
  public function something() {
    print "throwing AnotherException\n";
    throw new AnotherException();
  }
  public function somethingElse() {
    print "throwing MyException\n";
    throw new MyException();
  }
}

$a = new Foo();

try {
  try {
    $a->something();    

  } catch(AnotherException $e) {
    print "caught AnotherException\n";
    $a->somethingElse();    
  } catch(MyException $e) {
    print "caught MyException\n";
  }
} catch(Exception $e) {
  print "caught Exception\n";
}

我希望这个输出:

throwing AnotherException
caught AnotherException
throwing MyException
caught MyException

但它却输出:

throwing AnotherException
caught AnotherException
throwing MyException
caught Exception

谁能解释为什么它“跳过” catch(MyException $e) ?

谢谢。

【问题讨论】:

    标签: php exception-handling


    【解决方案1】:

    异常处理程序在其 try 块范围内捕获由代码引发的异常。

    $a->somethingElse() 的调用不会发生在与跳过的异常处理程序关联的try 块中。它出现在另一个 catch 子句中。

    仅仅因为它实际出现在引发异常的行下方并不足以使其覆盖该代码。

    缩进大括号的样式选择使这一点不太清楚,恕我直言。前一个 try 块的右大括号与下一个 catch 出现在同一行,即使它们是不相关的(兄弟)作用域。

    【讨论】:

    • 我只是想确保我们在同一页面上......基本上他应该在第一个catch之后添加另一个try,对吧?那么,因为整个事情都嵌入到更大的try中,他会得到3组异常吗?本质上它永远不会捕获第二个异常,因为它从不尝试?
    • 如果他将外部catch 更改为“MyException”而不是“Exception”,这是否会捕获“MyException”throw?问题是他的尝试触发了“MyException”的throw,但由于尝试不是由try 发起的,catch 永远不会发生?换句话说,“MyException”是否仍然会被第三个catch 捕获?
    • @Anthony,回复:第一条评论:是的,如果他添加了第三级 try 块,那将是一个解决方案。不过有点乱。我不会选择像你在最后一句话中描述的那样描述问题,但这并没有错误
    • @Anthony,回复:第二条评论,第一个问题:是的,如果他按照您的描述更改了外部捕获,它将捕获异常,但外部捕获已经捕获异常!它将它捕获为 Exception 而不是 MyException,但它是相同的异常!
    【解决方案2】:

    只是因为评论中没有足够的空间。将 try...catch 视为 if...else 循环。您不会期望以下内容:

    $a = 10;
    if($a == 9)
        print "\$a == 9";
    elseif($a == 10) {
        $a = 11;
        echo "now \$a == 11";
    } elseif($a == 11) {
        echo "\$a == 11";
    }
    

    打印出最后一个条件 ("\$a == 11"),因为第一个 elseif 已经满足条件。 try...catch 也是如此。如果满足条件,则不会继续在同一范围内搜索新的条件。

    【讨论】:

      【解决方案3】:

      我不确定以下是否合法(在 catch 块中“尝试”),但确实给出了预期的输出:

      class MyException extends Exception {}
      class AnotherException extends MyException {}
      
      class Foo {
        public function something() {
          print "throwing AnotherException\n";
          throw new AnotherException();
        }
        public function somethingElse() {
          print "throwing MyException\n";
          throw new MyException();
        }
      }
      
      $a = new Foo();
      
      try {
         try {
            $a->something();
         } catch(AnotherException $e) {
             print "caught AnotherException\n";
             try{
                $a->somethingElse();
             } catch(MyException $e) {
                print "caught MyException\n";
             }
         }
      } catch(Exception $e) {
        print "caught Exception\n";
      }
      

      给出输出:

      throwing AnotherException
      caught AnotherException
      throwing MyException
      caught MyException
      

      【讨论】:

        【解决方案4】:

        不确定这是否被认为已回答,但答案比这里提出的更简单。对于每次尝试,只能触发一个 catch 块,并且它始终是最具体的适用块。

        在这种情况下,AnotherException 被内部 try/catch 的第一个 catch 块抛出和处理,因此它不会被第二个 catch 块处理。在 catch 块中抛出的新异常由外部 try/catch 处理。

        【讨论】:

          猜你喜欢
          • 2020-08-01
          • 1970-01-01
          • 2014-12-31
          • 1970-01-01
          • 1970-01-01
          • 2017-05-10
          • 1970-01-01
          • 2021-07-19
          • 1970-01-01
          相关资源
          最近更新 更多