JAVA異常使用_每一個人都曾用過、但未必都用得好

1、拋出異常 vs. 返回錯誤代碼

有人說「Well, an exception is a goto.」,但也有人言「makes the code simpler by visibly separating the general case of expected processing from the special cases of errors.」spring

 

簡單地分析一下二者優劣。異常的優勢:讓代碼更簡潔,再也不處處if-return;不管CheckedEx仍是UnCheckEx都會強迫調用方或系統處理;Exception Chain和繼承體系,能夠解耦檢測錯誤和錯誤處理,方便包裝異常和控制錯誤鏈;異常調試方便,能夠跟蹤到引起異常的源指令。異常的缺點,除了效率慢以外,最重要的一點是很難知道應該try-catch具體神馬。例:apache

badly exception-based exception安全

not badly exception-based exception框架

很難發現由於先初始化Visible=true、在new Icon時拋異常致使錯誤邏輯的情景。但對於ErrorCode而言,因爲大量的if-return、更容易辨識邏輯的正確性。函數

ErrorCode的優勢在於清楚每個具體的錯誤類型Code,但你必定不清楚可能捕獲多少具體Exception;返回一種結果狀態,如0〜成功、-1〜失敗;將Error的傳播層限制在父層,對於Exception Chain而言,「The thrower of an exception is specifically relinquishing the right to have any expectations about how the exception will be handled.」;易於CodeReview以及保證編寫邏輯正確性,被用於編寫操做系統、底層驅動等等。但有許多缺點,沒有像Exception的鏈式處理等諸多優勢,並且常常忘記檢測返回是否成功、須要頻繁變動ErrorCode等數據類型。ui

對於Exception和ErrorCode而言,須要找到二者的平衡點,有如下一些原則:this

一、對於絕大部分代碼而言,Exception更加安全,到少會有異常體系去處理,再不濟也就程序異常 終止;但針對須要well-reviewed的關鍵代碼,適宜採用ErrorCode;google

二、若是涉及到與業務邏輯相關的代碼,最好採用ErrorCode;業務邏輯無關的代碼,如傳入參數校驗,採用Exception;spa

三、除了trying以外沒有處理邏輯和更多優點的狀況,最好採用Exception;操作系統

四、遠程接口實現中,僅採用ErrorCode。由於遠程調用框架對Exception的支持度等具備較大差別。

2、怎樣拋出異常&ErrorCode

僅當涉及到業務邏輯錯誤的狀況下拋出異常,注意幾點:

一、一個系統中至多有3〜5個具體自定義異常,如ibatis就僅5個左右;

二、若是Caller負責在調用以前檢測條件,則應該拋出UnCheckedEx,不然拋出CheckedEx;

三、遠程調用必定要try-catch;

四、ErrorCode應該採用Code+String形式,如:

五、return ErrorCode應當採用「{object, error}」的形式,如:


e.g:一個異常體系設計示例

3、參數校驗

參數校驗,是一類比較容易觸發返回ErrorCode或拋Exception的行爲。有類規則:

一、Api入參校驗採用Exception方式;

二、容許出錯的參數校驗、採用ErrorCode方式。

參數校驗有幾類經常使用包,如:

com.google.common.base.Preconditions

org.springframework.validation.ValidationUtils

org.apache.commons.lang.Validate

不太推薦使用Spring的ValidationUtils,太過依賴Spring框架、向後擴展性不強。Guava庫的Preconditions vs. Apache的Validate:

一、Preconditions校驗可拋出不一樣異常,如checkArgument throws IllegalArgumentException、checkNotNull throws NullPointerException等,Validate則僅拋出一種IllegalArgumentException;

二、Message參數,Preconditions適爲靈活,Validate不支持StringFormat,如:

Validate.isTrue(i > 0, "Should be positive but was: " + i);

Validate.isTrue(i > 0, "Should be positive but was: ", i);

checkArgument(i > MIN, "Expected more than %s, got %s", MIN, i);

三、集合判斷,Apache有幾個額外的函數:

  • Validate.notEmpty(Collection collection)

  • Validate.notEmpty(Map map)

  • Validate.notEmpty(Object[] array)

  • Validate.noNullElements(Collection collection)

  • Validate.noNullElements(Object[] array)

而Precondictions使用則比較麻煩:checkArgument(isNotEmpty(list));

四、Precondictions能夠一條語句搞定判斷後賦值,this.field = checkNotNull(parameter);

五、比較陳舊的系統,推薦使用Validate;


http://c2.com/cgi/wiki?AvoidExceptionsWheneverPossible

http://piotrjagielski.com/blog/google-guava-vs-apache-commons-for-argument-validation/

相關文章
相關標籤/搜索