2013-10-03 123 views
23

這對我來說很奇怪。 RuntimeException繼承自Exception,其繼承自Throwable爲什麼不捕獲異常catch runtimeException?

catch(Exception exc) { /* won't catch RuntimeException */ 

catch(Throwable exc) { /* will catch RuntimeException */ 

我知道RuntimeException是它的選中特殊。但根據我的理解,這隻適用於是否要聲明例外,而不是它們是否被捕獲。即使如此,我不知道爲什麼這個邏輯會突破Throwable。

這與我很相關,因爲我有一種情況,RuntimeExceptions可以在終端操作中拋出。我不確定這個模式的名字,但是像我的類EmailRoller需要一個Callbacks的數組。代碼如下所示:

for(Callback cb : callbacks) { 
    try { 
     cb.call(item); 
    } 
    catch(Exception exc) { 
     logger.error("Error in callback: ", exc); 
    } 
} 

因此,這是一樣的東西OOME需要飛過,因爲如果這些回調的一個消耗所有的計算機內存的情況下,那肯定是赫克是要影響的運行其他的。但是一個NullPointerException?或者是IndexOutOfBoundsException?這些會影響回調,但不會阻止其他人運行。

此外,這是一個企業設計。不同的程序員或團隊可以添加回調來處理該項目,但它們應該彼此隔離。這意味着,作爲負責隔離這些回調的程序員,我不應該依賴它們來確保錯誤不會漏過。捕捉Exception應該是正確的路線,但它不是因爲RuntimeException滑倒。所以我更普遍的問題是:這裏有什麼好的模式?只是catch(Exception | RuntimeException exc),我認爲這是一個語法錯誤,因爲繼承?

回答

81

這個問題的前提是有缺陷的,因爲捕捉Exception確實是 catch RuntimeException。演示代碼:

public class Test { 
    public static void main(String[] args) { 
     try { 
      throw new RuntimeException("Bang"); 
     } catch (Exception e) { 
      System.out.println("I caught: " + e); 
     } 
    } 
} 

輸出:

I caught: java.lang.RuntimeException: Bang 

你的循環會出現問題,如果:

  • callbacks爲空,而循環執行
  • 任何修改callbacks(如果它是一個集合而不是一個陣列)

也許這就是你所看到的?

+2

重讀我的代碼。這是正確的。由於運行時異常來自「if(results.foo.bar()){/ * apply callback * /}」,它是一個NPE,所以我的絕緣層很麻煩。 – djechlin

+6

@djechlin:你的帖子不會*顯示*'if(results.foo.bar())' - 現在還不清楚你到底要問什麼...... –

18
catch (Exception ex) { ... } 

will catch RuntimeException。

無論你放在catch塊中,都會被捕獲以及它的子類。

7

追趕Exception將搭上RuntimeException

2

我遇到了類似的情況。這是因爲classA的初始化依賴於classB的初始化。當classB的靜態塊面臨運行時異常時,classB未初始化。正因爲如此,classB沒有拋出任何異常,classA的初始化也失敗了。

class A{//this class will never be initialized because class B won't intialize 
    static{ 
    try{ 
     classB.someStaticMethod(); 
    }catch(Exception e){ 
     sysout("This comment will never be printed"); 
    } 
} 
} 

class B{//this class will never be initialized 
static{ 
    int i = 1/0;//throw run time exception 
} 

public static void someStaticMethod(){} 
} 

是的......捕捉Exception也會捕捉運行時異常。