Java異常封裝(轉)


一、分析 

Java語言的異常處理機制可以確保程序的健壯性,提高 系統的開發效率,但是Java API提供的異常都是比較低級(這里的低級指的是“低級別的異常”),只有開發人員才能看的懂,才明白發生了什么問題。對於終端用戶來說,這些異常基本上是天書,與業務無關,是純計算機語言的描述。 
這就需要我們對異常進行封裝了。 
二、場景 
異常封裝有三方面的優點: 
1.提高系統的友好性 
例如,打開一個文件,如果文件不存在,則會報FileNotFoundException異常,如果該方法的編寫不做任何處理,直接上拋上層,則會降低系統的友好性,代碼如下所示: 
[java]  
public static void doStuff()throws Exception{   
    InputStream is = new FileInputStream("無效文件.txt");   
    /*文件操作*/   
}  
此時doStuff方法的友好性極差:出現異常時(比如文件不存在),該方法直接把FileNotFoundException異常拋出到上層應用中(或者是終端用戶),而上層應用(或用戶)要么自己處理,要么接着拋出,最終的結果就是讓用戶對着“天書”式的文字發呆,用戶不知道這是什么問題,只是系統告訴他”哦,我出錯了,什么錯誤?你自己看着辦吧“。 
解決辦法就是封裝異常,可以把系統的 閱讀者分為兩類:開發人員和用戶。開發人員查找問題,需要打印出堆棧信息,而用戶則需要了解具體的業務原因,比如文件太大,不能同時編寫文件等,代碼如下: 
[java]  
public static void doStuff2()throws MyBussinessException{   
    try{   
        InputStream is = new FileInputStream("無效文件.txt");   
    }catch(FileNotFoundException e){   
        //為了方便開發和維護人員而設置的異常信息   
        e.printStackTree();   
        //拋出業務異常   
        throw new MyBussinessException(e);   
    }   
}   
 
2.提高系統的可維護性 
[java]  
public void doStuff(){   
    try{   
        //do something   
    }catch(Exception e){   
        e.printStackTrace();   
    }   
}   
這是很多程序員容易犯的錯誤,拋出異常是吧?分類處理多麻煩,就寫一個catch塊來處理所有異常吧。而且還信誓旦旦的說”JVM會打印出棧中的錯誤信息“,雖然這沒有錯,但是該信息只有開發人員自己才看的懂,維護人員看見這段異常基本上無法處理,因為需要深入到代碼邏輯中去分析問題。 
正確的做法是對異常進行分類處理,並進行封裝輸出,代碼如下: 
[java]  
public void doStuff(){   
try{   
    //do something   
    }catch(FileNotFoundException e){   
        log.info("文件夾未找到,使用默認配置文件....");   
    }catch(SecurityException 3){   
        log.info("無權訪問,可能原因是....");   
        e.printStackTrace();   
    }   
}   
如此包裝后,維護人員看到這樣子的異常就有了初步的判斷,或者檢查配置,或者初始化環境,不需要直接到代碼層級去分析了。 
 
3.解決Java異常機制自身的缺陷 
Java中的異常一次只能拋出一個,比如,doStuff方法有兩個邏輯代碼片段,如果在第一個邏輯片段中拋出異常,則第二個邏輯片段就不執行了,也就無法拋出第二個異常了。那么如何才能一次拋出兩個異常呢? 
其實,使用自行封裝的異常可以解決問題,代碼如下: 
[java]  
class MyException extends Exception{   
    //容納所有異常   
    private List<Throwable> causes = new ArrayList<Throwable>();   
    //構造函數,傳遞一個異常列表   
    public MyException(List<? extends Throwable> _causes){   
        cause.addAll(_causes);   
    }   
   
    //讀取所有的異常   
    public List<Throwable> getException(){   
        return causes;   
    }   
}   
MyException異常只是一個異常容器,可以容納多個異常,但它本身並不代表任何異常含義,它所解決的是一次拋出多個異常的問題,具體調用如下: 
[java] 
public static void doStuff()throws MyException{   
    List<Throwable> list = new ArrayList<Throwable>();   
    //第一個邏輯片段   
    try{   
        //Do something   
    }catch(Exception e){   
        list.add(e);   
    }   
   
    //第二個邏輯片段   
    try{   
        //Do something   
    }catch(Exception e){   
        list.add(e);   
    }   
   
    //檢查是否有必要拋出異常   
    if(list.size() > 0){   
        throw new MyException(list);   
    }   
}   
這樣一來,doStuff方法的調用者就可以一次獲得多個異常,也能夠為用戶提供完整的例外情況說明。 
那么在什么情況下,需要一個方法拋出多個異常呢?比如Web界面注冊時,展示層依次把User對象傳遞給邏輯層,Register方法需要對各個Field進行校驗並注冊,例如,用戶名不能重復,密碼必須符合密碼策略等,不要出現第一次提交系統提示”用戶名重復“,在修改在提交后,系統提示“密碼長度少6位”的情況,這種操作模式用戶體驗非常糟糕,最好的解決辦法就是封裝異常,建立異常容器,一次性地對User對象進行校驗,然后返回所有異常。 
 
三、建議 
在開發的過程中,根據具體的情況和需要,對異常進行封裝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM