2013-12-12 100 views
0

當我編譯下面的代碼一切順利,並預期輸出:爲什麼我不能用try/catch子句處理Exception e?

class Propogate { 
    public static void main(String[] args) { 
     Propogate obj = new Propogate(); 
     try { 
      obj.reverse(""); 
     } catch (IllegalArgumentException e) { 
      System.out.println(e); 
     } finally { 
      System.out.println("That's all folks"); 
     } 
    } 
    String reverse(String s) { 
     if(s.length() == 00) { 
      throw new IllegalArgumentException(); 
     } 
     String reversed = ""; 
     for(int i=s.length() - 1; i >= 0; --i) { 
      reversed += s.charAt(i); 
     } 
     return reversed; 
    } 
} 

計劃結果:

java.lang.IllegalArgumentException 
That's all folks 

然而,當我運行完全相同的代碼,但是從

改變異常類型
IllegalArgumentException to plain old exception all I get is:Propogate.java:14: error:  
unreported exception Exception; must be caught or declared to be thrown 
         throw new Exception(); 
        ^
1 error 

父類型有什麼特殊的Exception(),我不能用try/catch語句處理它?爲什麼IllegalArgumentException()允許我用try/catch語句處理它就好了。這些都是一種在晚上保持清醒的想法,只有參加SCJP考試纔會失敗。

+1

你更改爲'Exception'的哪個? 「扔」或「抓」? – rgettman

+0

我改變了投擲和捕捉的類型。 – paniclater

+0

阿加!這個詞是「傳播」......不是「傳播」。 –

回答

5

其中拋出異常不是的RuntimeException一個子類必須聲明它拋出Exception的方法。你必須寫

String reverse(String s) throws Exception { 

如果你打算拋出一個Exception它。一旦你這樣做,你可以通過try/catch正常捕捉它。

+0

所以當你在方法聲明中添加「throws Exception」就像告訴編譯器:「相信我,我會在別的地方抓到這個?」 – paniclater

+0

編譯器不會信任你。它會增強你在別的地方抓住它的機會。 –

+0

謝謝,我想我終於開始把這個包裹起來。 – paniclater

1

IllegalArgumentException s是未經檢查的例外,因爲它們是RuntimeException的子類。所以編譯器不會去檢查它們。非RuntimeException對象,例如Exception,由編譯器檢查,這解釋了您所看到的內容。

因爲您正在捕捉調用堆棧底部的main()中的例外情況,所以我認爲最好用catch (Exception e)代替所有意外情況。

+0

因此,如果我想在代碼中傳播和捕獲異常,我需要確保它是RuntimeException的一個子類(未經檢查的異常)? – paniclater

+0

不,您可以拋出並捕獲檢查到的異常和未檢查的異常。我認爲像你一樣拋出'IllegalArgumentException'就沒有問題。但是如果你想拋出一個簡單的'Exception',@LouisWasserman說他需要聲明'拋出異常'時它是正確的。 –

+0

對。這對我行得通。 – paniclater

1

引發作爲RuntimeException的子類的異常的方法不必聲明它會在該方法後面引發該異常。這就是爲什麼第一個代碼很好。

但是,如果將異常類型更改爲Non-RuntimeException,則必須使該方法拋出異常,否則將發生編譯錯誤。這就是爲什麼第二個代碼出錯的原因。

0

其他答案已經涵蓋了爲什麼編譯器不滿意,你可以做些什麼。但我認爲你真正的錯誤是首先投擲Exception

投擲Exception幾乎總是一個壞主意。原因是,如果你的代碼拋出Exception,它(或其他人的代碼)通常必須捕獲​​異常。但是捕獲Exception的問題是您的代碼還會捕獲可能由您的代碼拋出的任何/所有子類型Exception。這包括可能由代碼中的錯誤等引起的未經檢查的異常。

例如:

public class Test { 
    private static Integer a; 
    private static Integer b; 

    public static void main(String[] args) { 
     try { 
      if (a.equals(b)) { 
       throw Exception("they are the same"); 
      } 
      System.out.println("they are different"); 
     } catch (Exception ex) { 
      System.out.println(ex.message()); 
     } 
    } 
} 

當你運行它,你會得到神祕的輸出 「空」。 (爲讀者練習......明確原因。)

聲明的方法爲throws Exception更差,因爲現在呼叫者被迫要麼抓Exception(壞的),或者它傳播(差)。聲明爲throws Exception的方法就像癌症一樣。

聲明main方法爲throws Exception是一種特殊情況。主要方法(通常)由JVM基礎結構調用,旨在處理任何異常。它只是打印一個堆棧跟蹤到標準錯誤。即便如此,你也可以自己處理異常情況。在「生產級」代碼庫中,通常需要在錯誤日誌中記錄意外的異常。

相關問題