讀古今文學網 > 編寫高質量代碼:改善Java程序的151個建議 > 建議116:異常只為異常服務 >

建議116:異常只為異常服務

異常只為異常服務,這是何解?難道異常還能為其他服務不成?確實能,異常原本是正常邏輯的一個補充,但是有時候會被當作主邏輯使用,看如下代碼:


//判斷一個枚舉是否包含String枚舉項

public static<T extends Enum<T>>boolean Contain(Class<T>c, String name){

boolean result=false;

try{

Enum.valueOf(c, name);

result=true;

}catch(RuntimeException e){

//只要是拋出異常,則認為是不包含

}

return result;

}


判斷一個枚舉是否包含指定的枚舉項,這裡會根據valueOf方法是否拋出異常來進行判斷,如果拋出異常(一般是IllegalArgumentException異常),則認為是不包含,若不拋出異常則可以認為包含該枚舉項,看上去這段代碼很正常,但是其中卻有三個錯誤:

異常判斷降低了系統性能。

降低了代碼的可讀性,只有詳細瞭解valueOf方法的人才能讀懂這樣的代碼,因為valueOf拋出的是一個非受檢異常。

隱藏了運行期可能產生的錯誤,catch到異常,但沒有做任何處理。

我們這段代碼是用一段異常實現了一個正常的業務邏輯,這導致代碼產生了壞味道。要解決此問題也很容易,即不在主邏輯中使用異常,代碼如下:


//判斷一個枚舉是否包含String枚舉項

public static<T extends Enum<T>>boolean Contain(Class<T>c, String name){

//遍歷枚舉項

for(T t:c.getEnumConstants()){

//枚舉項名稱是否相等

if(t.name().equals(name)){

return true;

}

}

return false;

}


異常只能用在非正常的情況下,不能成為正常情況的主邏輯,也就是說,異常只是主場景中的輔助場景,不能喧賓奪主。

而且,異常雖然是描述例外事件的,但能避免則避免之,除非是確實無法避免的異常,例如:


public static void main(Stringargs){

File file=new File("文件.txt");

try{

FileInputStream fis=new FileInputStream(file);

/*其他業務邏輯處理*/

}catch(FileNotFoundException e){

//異常處理

}

}


這樣一段代碼經常會在我們的項目中出現,但經常寫並不代表不可優化,這裡的異常類FileNotFoundException完全可以在它誕生前就消除掉:先判斷文件是否存在,然後再生成FileInputStream對象,代碼如下:


public static void main(Stringargs){

File file=new File("文件.txt");

//經常出現的異常情況,可以先做判斷

if(fle.exists()&&!fle.isDirectory()){

try{

}catch(){

}

}

}


雖然增加了if判斷語句,增加了代碼量,但是卻會減少FileNotFoundException異常出現的幾率,提高了程序的性能和穩定性。

注意 異常只為確實異常的事件服務。