Checked vs UnChecked Exception ,使用場合?

來源:互聯網
上載者:User

from : 出處:網俠

 

Checked vs UnChecked 異常 ,使用場合?

 

異常的概念  

       任何的異常都是Throwable類(為何不是介面??),並且在它之下包含兩個字類Error / Exception,而Error僅在當在Java虛擬機器中發生動態串連失敗或其它的定位失敗的時候,Java虛擬機器拋出一個Error對象。典型的簡易程式不捕獲或拋出Errors對象,你可能永遠不會遇到需要執行個體化Error的應用,那就讓我們關心一下Exception。

       Exception中比較重要的就是RuntimeException(運行時異常)-可能在執行方法期間拋出但未被捕獲的 RuntimeException 的任何子類都無需在 throws 子句中進行聲明,也就是說你的應用應該不去“關心”(說不關心是不服責任的,但只是你不應該試圖執行個體化它的字類)。  RuntimeException,就如同你不應該關心Error的產生與處理一樣!RuntimeException描述的是程式的錯誤引起來的,因該由程式負擔這個責任!(從責任這個角度看Error屬於JVM需要負擔的責任;RuntimeException是程式應該負擔的責任;checked exception 是具體應用負擔的責任)

       除了Error與RuntimeException,其他剩下的異常都是你需要關心的,而這些異常類統稱為Checked Exception,至於Error與RuntimeException則被統稱為Unchecked Exception.

         關於 Java 中引入的 Checked Exceptions,目前存在著很多反對意見。正方的觀點是引入 Checked Exceptions,可以增加程度的魯棒性。反方的觀點是 Checked Exceptions 很少被開發人員正確使用過,並且降低了程式開發的生產率和代碼的執行效率。

Java 中定義了兩類異常: 

1) Checked exception: 這類異常都是Exception的子類 。異常的向上拋出機制進行處理,如果子類可能產生A異常,那麼在父類中也必須throws A異常。可能導致的問題:代碼效率低,耦合度過高。C#中就沒有使用這種異常機制。

2) Unchecked exception: 這類異常都是RuntimeException的子類,雖然RuntimeException同樣也是Exception的子類,但是它們是特殊的,它們不能通過client code來試圖解決,所以稱為Unchecked exception 。  

   

(JAVA視線論壇robbin's view,個人覺得用來做商務程序控制違背了Exception設計的初衷,但可以借鑒一下)

     在使用UseCase來描述一個情境的時候,有一個主事件流和n個異常流。異常流可能發生在主事件流的過程,而try語句裡面實現的是主事件流,而catch裡面實現的是異常流,在這裡Exception不代表程式出現了異常或者錯誤,Exception只是物件導向化的商務邏輯控制方法。如果沒有明白這一點,那麼我認為並沒有真正明白應該怎麼使用Java來正確的編程。 
      而我自己寫的程式,會自訂大量的Exception類,所有這些Exception類都不意味著程式出現了異常或者錯誤,只是代表非主事件流的發生的,用來進行那些分支流程的流程式控制制的。例如你往許可權系統中增加一個使用者,應該定義1個異常類,UserExistedException,拋出這個異常不代表你插入動作失敗,只說明你碰到一個分支流程,留待後面的catch中來處理這個分支流程。傳統的程式員會寫一個if else來處理,而一個合格的OOP程式員應該有意識的使用try catch 方式來區分主事件流和n個分支流程的處理,通過try catch,而不是if else來從代碼上把不同的事件流隔離開來進行分別的代碼撰寫。

(另外一種觀點,不同於robbin,個人贊同,並引用於此)

1。什麼時候拋出異常--涉及到服務類
2。拋出checked還是unchecked的異常--涉及到客戶類

       對第一個問題來說,我想異常本身這個字解釋了某些東西,異常就是我們認為在正常情況下不可能發生的問題,並且服務代碼不知道如何去處理。譬如說我做一個監控程式,需要用壓縮卡提供的API去初始化所有的板卡,API提供的是boolean型的傳回值,但我把這個API變成拋出一個異常,因為除非特殊原因,我不認為會發生初始化失敗的情況,當然更不知道怎樣去處理這個問題。又譬如Hibernate裡面的LoadObject使用沒有發現這個對象存在,那Hibernate也是認為不可能的,除非其他代碼直接刪除了資料庫裡面的記錄,那麼也需要拋出異常。當然Hibernate本身也不知道如何處理這種情況。
       但是如果發生的情況是可以預期的,那我不認為應該拋出例外。象上面這個userExist的情況,我認為應該在前面已經分流,應該首先判斷這個使用者是否存在,if(userExists()),然後進行處理,而不應當拋出例外。以及login應當返回true或者false。也就是說,這些屬於程式的正常流程,而不是例外,不是異常。把例外作為正常程式流程的控制機制,只不過是把服務代碼中的if轉移到客戶代碼去,沒有減少任何需要處理的代碼,反而增加了系統的負擔(產生例外棧)。
       還有拋出異常的情況是違反方法的先決條件,每一個方法都有自己的先決條件和後置條件,方法只有在正確的前提下才能執行達到一個正確的後果,(所謂類的不變數)。譬如你去存取一個數組的某一個元素,這個存取方法有一個前提條件,就是你的索引應當落入它的最大下標和最小下標之間,不然就應當拋出一個例外。

         對於第二個問題,端視於客戶代碼是否能夠根據這個例外進行合理的處理。如果客戶代碼根本就不知道如何處理這個例外,應當把它作為一個unchecked例外,例如上面下標的問題,客戶代碼用一個不合法的下標來存取數組,那麼拋出一個checked例外以後,客戶代碼是+1還是-1?顯然根本就不可能做出“合理的”處理,客戶既然不能處理,還要強制它去處理,那麼就是捕獲,列印了事,沒有增加任何價值。但是如果是客戶可以處理的,或者可以選擇不同的方式處理的,那麼就可能需要用checked,但我發現很少有這樣的情況。對於類似於RemoteException或者SQLException這些Exception,我一般都轉換為具體的業務Exception,而我所有的業務Exception都是RuntimeException.

         所以我的觀點是,是否拋出例外就是服務代碼是否進行合理的處理,拋出什麼類型的例外就是客戶代碼是否能夠合理的處理。

保護封裝性的代碼執行個體:

      不要讓你要拋出的checked exception升級到較高的層次。例如,不要讓SQLException延伸到業務層。業務層並不需要(不關心?)SQLException。你有兩種方法來解決這種問題:

 1)轉變SQLException為另外一個checked exception,如果用戶端並不需要恢複這種異常的話;
 2)轉變SQLException為一個unchecked exception,如果用戶端對這種異常無能為力的話;

      多數情況下,用戶端代碼都是對SQLException無能為力的,因此你要毫不猶豫的把它轉變為一個unchecked exception,看看下邊的代碼:

public void dataAccessCode(){
try{
      .  .some code that throws SQLException
}catch(SQLException ex){
     ex.printStacktrace();
}
}

 

上邊的catch塊緊緊列印異常資訊而沒有任何的直接操作,這是情有可原的,因為對於SQLException你還奢望用戶端做些什麼呢?(但是顯然這種就象什麼事情都沒發生一樣的做法是不可取的)那麼有沒有另外一種更加可行的方法呢? 看下面代碼:
public void dataAccessCode(){
try{
     ..some code that throws SQLException
}catch(SQLException ex){
    throw new RuntimeException(ex);
}
}
     上邊的做法是把SQLException轉換為RuntimeException,一旦SQLException被拋出,那麼程式將拋出RuntimeException,此時程式被掛起並返回用戶端異常資訊。 調用該方法的程式碼中也不用再捕獲SQLException異常:

 

public void do(){

     dataAccessCode();   
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.