2010-05-01 44 views
14

我想問,爲什麼我們不需要將try-catch塊添加到RuntimeException,而我們應該使用其他例外來做到這一點?爲什麼我們不必將try-catch添加到RuntimeException中?

我的意思是這樣的:

public class Main { 
    public static void main(String[] args) { 
     throw new RuntimeException(); 
    } 
} 

編輯: 當我說:throw new RuntimeException();它是如此清楚,有一個例外會發生,爲什麼編譯器不禁止呢?

+6

請注意,當發生編程/代碼邏輯錯誤時,通常會引發'RuntimeExceptions'。解決方案通常只是修補代碼。你通常不應該抓住他們。 – BalusC 2010-05-01 16:21:06

+0

真的嗎?我認爲最好的做法之一是將檢查到的異常轉換爲未經檢查的異常,而不是將它們全部在一個地方顯示給用戶? – vodkhang 2010-05-01 16:41:45

+0

@vodkhang我想說的是,爲什麼編譯器不會禁止代碼,當它清楚地發生RuntimeException將會發生。 – 2010-05-01 16:56:40

回答

25

這是因爲它是一個選中例外。它不需要顯式聲明或捕獲。另請參閱Sun tutorial on the subject

更新:在一般情況下,你應該只拋出一個RuntimeException(最好在Javadoc上市,其subclasses之一)發出信號,表明來電者做錯了。即傳遞一個null參數(再拋NullPointerException),或非法參數(再拋IllegalArgumentException),或者該方法被稱爲在錯誤的時刻/狀態(再拋IllegalStateException),等等。調用者應該修復他們的代碼以避免這種情況。例如。事先檢查參數是否爲空,或者參數的格式/語法是否正確,或者確保在適當的時候調用該方法。

如果有一個特定的情況應該拋出一個運行時異常,並且你不能使用它的某個特定的子類,那麼你應該擴展它,並在新的異常的javadoc和調用方法中正確地記錄它,例如ConfigurationException extends RuntimeException用於調用代碼在使用前沒有正確配置應用程序/ API的情況。這應該表明最終用戶(另一個開發人員)足以採取相應的行動。

在概括地說:RuntimeExceptions應該確定其通過在代碼流或配置故障引起可恢復編程問題(讀:顯影劑的故障)。檢查Exceptions應識別由代碼外部的意外情況(例如數據庫關閉,文件I/O錯誤,錯誤的最終用戶輸入等)導致的編程式可恢復問題。 Errors應該以編程方式識別不可恢復的問題(例如,內存不足,初始化程序內的異常等)。

+0

但是當我說:「拋出新的RuntimeException();」很明顯會發生異常,那麼編譯器爲什麼不禁止它? – 2010-05-01 16:26:28

+0

異常沒有道德上的錯誤。未檢查的異常是故意不檢查的。因此這個名字沒有選中。 – 2010-05-01 16:34:25

+0

@ M.H不,現在還不清楚。一個例子是List.add()方法,這是一個普通的列表實現,像arraylist永遠不會拋出一個UnsupportedOperationException異常,所以不需要它在異常簽名中。方法Collections.asUnmodifyableList()將返回一個List,它將在對List.add的調用中拋出UnsupportedOperationException。 List.add的實現只包含throw new UnsupportedOperationException。只有List類型的對象,你不能看到異常是否會被拋出,而普通列表不應該拋出它。 – josefx 2010-05-01 16:43:47

2

RuntimeException,Error及其子類特別沒有編譯時檢查 - 它們不是該方法正式合同的一部分。

請參閱JLS中的第11章,異常,特別是11.2,異常的編譯時檢查。

2

讓我們認爲這種方式。如果NullPointerException被設計爲編譯時異常會怎麼樣?如果這樣做,編譯器必須嚴格檢查變量是否爲空。這是無法完成的。

public void dummyMethod(Object obj){ 

} 

這裏沒有辦法讓編譯器檢查obj是否可以爲null。但是,當您有空指針場景時,必須引發一些錯誤/異常。

+0

你是否聲稱如果NullPointerException是一個檢查異常它會引入一些基本約束?我沒有得到你提供的例子嗎?在某些實現中,接受obj == null的方法可能會非常有意義。 – aioobe 2010-05-01 16:50:44

+0

我只是想讓你從設計的角度思考。它完全合乎邏輯地同時被選中和未被選中。現在,爲了讓編譯器檢查這些規則,您必須設置RuntimeException爲1的類型,並且NullPointerException是它的一種類型。對你的問題的回答是肯定的,這是NPE檢查時的一個概率。我提供的例子是告訴傳遞給該方法的Object obj可以是且不能爲null,並且此方法對此不知道。編譯器不能檢查這些實例。 – bragboy 2010-05-01 16:58:26

1

因爲不會拋出運行時異常並且不必聲明運行時異常。你的程序是一個有效的Java程序,所以編譯器沒有理由抱怨。

1

基本上,未捕獲的異常只是顯示消息和終止應用程序的簡寫。

爲什麼你需要這樣做?在某些情況下,您可以檢測到出現問題,某些文件未加載,api丟失,某些數據出於某種原因已損壞,或者其他一百萬個其他數據中的一個出錯。如果你不拋出異常,應用程序可能會在另一個點崩潰,或者在最壞的情況下,在錯誤升級時繼續運行,這使得調試更加困難。

重要的是要明白,一個拋出異常,因爲有一個錯誤,異常不是錯誤,它只是信使。

+0

+1謝謝你非常有用的答案 – 2010-05-02 18:40:50

2

每語言規範,unchecked異常是在編譯時這意味着編譯器不要求的方法來捕獲或指定(用throws)他們不檢查。屬於這一類的類在JLS的部分11.2 Compile-Time Checking of Exceptions詳細:

unchecked異常類是類RuntimeException和它的子類,類Error及其子類。所有其他異常類別爲已檢查異常類別。 Java API定義了許多異常類,既可以選中也可以不選中。額外的異常類,既可以選中也可以不選中,可以由程序員聲明。請參閱§11.5瞭解異常類層次結構的描述以及由Java API和Java虛擬機定義的一些異常類。

因此,因爲RuntimeException在未檢查的異常中,編譯器不會強制您處理它。如果您想強制一段代碼的調用者處理異常,請使用檢查的異常(除RuntimeException以外的Exception的子類均爲檢查異常類)。

1

在這個論壇上的大部分答案一直在討論Exception層次結構和Java編譯器沒有捕獲它們,但我會嘗試從設計角度回答這個問題,爲什麼也許這樣設計。

基本上當你調用一個函數(或寫一些代碼)的異常可以根據三種不同的情況被扔出來的:

  1. 根據一個不可避免的條件如網絡或一些不可用文件系統上缺少預期的文件。

  2. 基於可避免的,但已知的條件Integer.parseInt(String)可以拋出NumberFormatException如果主叫方傳遞一個不能轉換的串像"Hello",但主叫方可以確保到位正確驗證的任何字符串傳遞給函數之前,徹底廢除並有可能產生異常。一個常見的用例可能是在將網頁傳遞給進行轉換的更深層之前,在網頁上驗證表單域age

  3. 一個未知的或意外的情況任何時候的一些代碼行可以在你的代碼,因爲有一些錯誤,你這樣做,直到它在生產升空並沒有觀察到錯誤條件拋出一個異常,一般情況與NullPointer ReferenceIndexOutOfBounds等,而如果觀察到將可能落入類別2

1類的異常通常被設計爲Checked Exceptions,因爲它需要執行爲不可避免的錯誤條件的檢查,並執行其回退。例如,IOException是檢查異常,因爲如果你打開一個文件,可能會有很多事情可能會出錯(如文件可能被刪除,權限等),並預先驗證所有這些都可能非常麻煩。

第二種類型的例外通常建模爲Unchecked Exceptions,因爲您可能已經進行了預驗證,並且在您已經處理的情況下被迫使用try and catch可能會令人惱怒。

第三種類型的異常不需要甚至擔心,因爲您不能在應用程序代碼的每個語句中出現意外出現的錯誤處理。但是有時候你可以放置一個全局處理器,在調用堆棧中的某處,幾乎所有的應用程序代碼都被執行,並以通用的方式處理它,這樣應用程序就不會因意外錯誤而崩潰。

例如,如果您運行的是Web應用程序,則可以配置您的Servlet容器以發送一個通用的500 Internal Server Error用於應用程序中的任何未處理的錯誤。或者,如果您正在運行獨立的Java應用程序,則可以將main method的內容保留在try catch塊中以防止應用程序崩潰。

相關問題