2010-04-06 94 views
10

我用下面的代碼混淆困惑:當前PHP異常在try..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"; 
    $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)?

謝謝。

回答

14

異常處理程序捕獲其try塊範圍內的代碼引發的異常。

調用$a->somethingElse()不會發生在與跳過的異常處理程序關聯的try塊內。它發生在另一個catch子句中。

僅僅因爲它在物理上出現在引發異常的行的下方不足以使其覆蓋該代碼。

縮進牙套的樣式選擇使得這個不太清晰,恕我直言。前一個try塊的大括號與下一個catch出現在同一行,即使它們不相關(好,兄弟)範圍。

+0

我只是想成爲確定我們在同一頁面......基本上他應該在第一個「catch」之後添加另一個'try',對吧?那麼,因爲整個事物都嵌入了更大的嘗試,他會得到3套例外?從本質上講,它永遠不會捕獲第二個異常,因爲它從不嘗試? – Anthony 2010-04-06 16:57:50

+0

如果他有,或者將外部'catch'改爲「MyException」而不是「Exception」,這是否會引發「MyException」'throw'?他的嘗試是否觸發「MyException」的'throw'的問題,但是因爲嘗試不是由'try'啓動的,catch'從不會發生?換句話說,「MyException」仍然在那裏被第三個「catch」抓住了嗎? – Anthony 2010-04-06 17:03:16

+0

@Anthony,re:第一條評論:是的,如果他添加了第三層的try塊,那將是一個解決方案。雖然有點雜亂。我不會選擇像上一句話那樣描述問題的特徵,但它不是錯誤的*。 – Oddthinking 2010-04-07 00:03:10

5

僅僅是因爲在評論中沒有足夠的空間來容納這一點。想想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也是如此。如果條件滿足,它不會繼續在同一範圍內搜索新條件。

0

不知道這是否被認爲是回答,但答案比這裏提出的更簡單。對於每一次嘗試,只有一個catch塊可以被觸發,並且它總是最適用的一個。

在這種情況下,AnotherException被內部try/catch的第一個catch塊引發和處理,所以它不會被第二個catch塊處理。在catch塊中引發的新異常由外部try/catch處理。

1

我不知道,如果下面是合法的(「嘗試」荷蘭國際集團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