java中的異常的超類是java.lang.Throwable(後文省略爲Throwable),它有兩個比較重要的子類,java.lang.Exception(後文省略爲Exception)和java.lang.Error(後文省略爲Error),其中Error由JVM虛擬機進行管理,如我們所熟知的OutOfMemoryError異常等,所以我們本文不關注Error異常,那麼我們細說一下Exception異常。
非受檢異常(unchecked Exception)
- Exception異常的子類RuntimeException或其他繼承自RuntimeException的子類
受檢異常(checked Exception)
- 其他繼承自Exception異常的子類
如何選擇異常
如果調用者可以處理,並且你也希望調用者進行處理,那麼就要拋出受檢異常,提醒調用者在使用你的方法時,考慮到如果拋出異常時如果進行處理,相似的,如果在寫某個方法時,你認爲這是個偶然異常,理論上說,你覺得運行時可能會碰到什麼問題,而這些問題也許不是必然發生的,也不需要調用者顯示的通過異常來判斷業務流程操作的,那麼這時就可以使用一個RuntimeException這樣的非受檢異常.
什麼時候才需要拋異常
如果你覺得某些”問題”解決不了了,那麼你就可以拋出異常了。比如,你在寫一個service,其中在寫到某段代碼處,你發現可能會產生問題,那麼就請拋出異常吧
應該拋出怎樣的異常
先從受檢異常說起,比如說有這樣一個業務邏輯,需要從某文件中讀取某個數據,這個讀取操作可能是由於文件被刪除等其他問題導致無法獲取從而出現讀取錯誤,那麼就要從redis或mysql數據庫中再去獲取此數據,參考如下代碼,getKey(Integer)爲入口程序.
public String getKey(Integer key){
String value;
try {
InputStream inputStream = getFiles("/file/nofile");
//接下來從流中讀取key的value指
value = ...;
} catch (Exception e) {
//如果拋出異常將從mysql或者redis進行取之
value = ...;
}
}
public InputStream getFiles(String path) throws Exception {
File file = new File(path);
InputStream inputStream = null;
try {
inputStream = new BufferedInputStream(new FileInputStream(file));
} catch (FileNotFoundException e) {
throw new Exception("I/O讀取錯誤",e.getCause());
}
return inputStream;
}
解析:
- 受檢異常可以控制義務邏輯,切記儘量不要這樣使用,這樣將異常的作用擴大化,會導致代碼複雜程度的增加,耦合性會提高,代碼可讀性降低等問題
- 如果調用者調用出錯後,一定要讓調用者對此錯誤進行處理纔可以,滿足這樣的要求時,我們纔會考慮使用受檢異常。
接下來,我們來看一下非受檢異常(RuntimeException),對於RuntimeException這種異常,我們其實很多見,比如java.lang.NullPointerException/java.lang.IllegalArgumentException等,那麼這種異常我們時候拋出呢?當我們在寫某個方法的時候,可能會偶然遇到某個錯誤,我們認爲這個問題時運行時可能爲發生的,並且理論上講,沒有這個問題的話,程序將會正常執行的時候,它不強制要求調用者一定要捕獲這個異常,此時拋出RuntimeException異常
public void test() {
myTest.getFiles("");
}
public File getFiles(String path) {
if(null == path || "".equals(path)){
throw new NullPointerException("路徑不能爲空!");
}
File file = new File(path);
return file;
}
解析:
如果調用者調用getFiles(String)的時候如果path是空,那麼就拋出空指針異常(它是RuntimeException的子類),調用者不用顯示的進行try…catch…操作進行強制處理.這就要求調用者在調用這樣的方法時先進行驗證,避免發生RuntimeException
總結出一個結論: RuntimeException異常和受檢異常之間的區別就是:是否強制要求調用者必須處理此異常,如果強制要求調用者必須進行處理,那麼就使用受檢異常,否則就選擇非受檢異常(RuntimeException)。一般來講,如果沒有特殊的要求,我們建議使用RuntimeException異常。