Java 異常處理從入門到實戰

異常處理是每一個項目裏很是重要的一部分,項目質量的高低好壞,與異常處理水平的高低好壞緊密相連。javascript

最近發現有不少開發者對 Java 異常處理沒有本身的認識和標準,有的具有2-3年開發經驗卻對異常處理仍然沒有深入地認識。前端

本問將從如下個方面介紹異常處理相關知識:java

  1. 爲何須要異常處理?程序員

  2. 你瞭解異常處理嗎?數據庫

  3. 異常處理有哪些原則?編程

  4. Java 異常處理機制介紹後端

  5. 異常處理對項目質量的影響數組

  6. 異常處理對工資待遇的影響網絡

 

異常是指程序在運行過程當中因爲外部問題(如硬件錯誤、輸入錯誤)等致使的程序異常事件。編程語言

異常處理是編程語言或計算機硬件裏的一種機制,用於處理軟件或信息系統中出現的異常情況(即超出程序正常執行流程的某些特殊的狀況)。

一、爲何須要異常處理?

 

在項目開發的過程當中,即便程序員把代碼寫得盡善盡美,在系統的運行過程當中仍然會遇到一些問題。由於不少問題不是靠代碼可以避免的,好比:客戶輸入數據的格式,讀取文件是否存在,網絡是否始終保持通暢等等。

程序運行時,發生的不被指望的事件,它阻止了程序按照程序員的預期正常執行,或者說程序未按照指望的流程執行,這就致使了異常的發生。

異常發生時,若是不進行任何處理,勢必致使程序不能正常運行,不能達到咱們所指望的結果。

所以在項目開發過程當中,異常處理機制是很是重要並且也是很是必要的,它能使咱們對程序運行的結果進行控制及異常發生時進行有效地處理,以達到程序的預期效果。

下面經過「用戶註冊」的例子說明爲何須要異常處理。

用戶註冊的用戶名稱要求長度不能超過32位。

咱們考慮一種狀況:用戶張三,輸入的用戶名稱爲「zhonghuarenmingongheguozhangsan666」,長度超過32位。

假設數據庫中用戶表的用戶名稱字段最大長度爲32位,那麼若是不考慮異常狀況,勢必在用戶提交註冊後,保存到數據庫的時候,數據庫必定會報錯「value too large for column」。

這樣的話,程序沒有作異常處理的話,程序產生的異常會直接反饋到前端界面上,用戶體驗極差。所以咱們須要對這類異常進行有效的處理,以保證良好的用戶體驗。

二、你瞭解異常處理嗎?

 

異常處理是每一個項目裏很是重要的一部分,項目質量的高低好壞,與異常處理水平的高低好壞緊密相連。最近發現有不少開發者對 Java 異常處理沒有本身的認識和標準,有的具有2-3年開發經驗卻對異常處理仍然沒有深入地認識。

下面我列舉幾種程序的場景,供你們參考。

一、通篇的程序沒有任何異常處理,任程序自生自滅,不作任何處理。

 

二、程序使用 throw 輸出錯誤給用戶。

 

三、程序使用 try...catch 進行一小段代碼的包括,catch 裏只打印了堆棧信息,或者 catch 裏什麼都沒作,或者把異常 throws 出去。

 

四、程序使用 try...catch 進行整段代碼的包括,catch 裏只打印了堆棧信息,或者 catch 裏什麼都沒作,或者把異常 throws 出去。

 

五、程序使用 try...catch 進行整段代碼的包括,catch 裏只打印了堆棧信息,而且輸出了相應的錯誤日誌。

 

六、程序使用 try...catch 進行整段代碼的包括,catch 裏只打印了堆棧信息,輸出了相應的錯誤日誌,而且 throws 了自定義異常,選擇友好的提示信息給用戶展現。

 

七、程序使用 try...catch 進行整段代碼的包括,輸出了相應的錯誤日誌,若是不是最外層調用則 catch 裏不打印堆棧信息,而且 throws 了自定義異常,同時把堆棧信息帶出去,最外層調用方,根據自定義異常,選擇友好的提示信息給用戶展現,而且打印出異常的堆棧信息。即程序根據實際狀況對異常進行了綜合處理,並經過日誌進行了異常的詳細記錄,以便覈查問題。

 

毫無疑問,第7種是程序進行異常處理的最有效手段。

 

三、異常處理有哪些原則

 

既然咱們知道異常處理對項目或者程序意義重大,那麼在面對具體的項目狀況,面對異常場景時,想要有效地進行異常處理,這裏面有哪些原則呢?

我總結爲如下「三大異常處理原則」。

1.程序層面異常處理原則

  • 要避免使用異常處理代替錯誤處理;

有的人寫代碼會用異常處理來作判斷邏輯或者作業務邏輯處理,這樣會下降程序的清晰性,而且效率低下。

  • 處理異常不能夠代替簡單測試,只能在異常狀況下使用異常機制;

  • 不要進行小粒度的異常處理,應該將整個業務代碼包裝在一個 try 語句塊中;

  • 異常每每在高層處理,且不能忽視每個異常

 

2.需求層面異常處理原則

  • 搞清楚業務邊界,用代碼防止異常;

在寫代碼以前,就要明確業務需求,同時瞭解該需求功能的邊界,寫代碼的時候,用專門的代碼來防止異常的發生。

  • 給用戶友好的提示;

在發現異常狀況後,代碼進行特殊處理後,給用戶友好的提示,不能直接拋出異常到用戶界面。

  • 程序員不定義業務異常流程。

業務需求是經過代碼來實現的,程序員通常不瞭解業務,所以在寫某個業務需求過程當中,發現處理不了的異常,必定要與客戶或者產品負責人來肯定異常流程,從業務邏輯層面,考慮異常處理的業務邏輯,程序員不去定義業務異常流程。

3.接口層面異常處理原則

  • 輸入、輸出參數校驗;

接口服務提供方通常要對輸入參數作校驗,校驗經過後,纔會提供服務。接口調用方通常要對輸出參數作校驗,校驗經過後,纔會使用服務。

  • 請求和響應的日誌記錄;

接口要對請求和響應作好日誌記錄,這在後期遇到問題反查的時候特別重要。

  • 接口超時等異常的業務處理。

接口開發時,常常會遇到接口超時等網絡問題,所以在開發的過程當中,尤爲要處理好這些異常。好比:超時反查機制,超時重發機制等。

四、Java 異常處理機制介紹

 

Java 異常類層次以下圖(Java 是採用面向對象的方式來處理異常的)。

 

640?wx_fmt=png

從上圖,能夠看出全部的異常跟錯誤都繼承於 Throwable 類,也就是說全部的異常都是一個對象。Exception 類是 Throwable 類的子類,除了 Exception 類外,Throwable 還有一個子類 Error 。

1.Error(錯誤)

Java 程序一般不捕獲錯誤。錯誤通常發生在嚴重故障時,它們在 Java 程序處理的範疇以外。Error 用來指示運行時環境發生的錯誤。

例如:JVM 運行時出現的 OutOfMemoryError 以及 Socket 編程時出現的端口占用等程序沒法處理的錯誤。程序通常不會從錯誤中恢復。

2.Exception(異常)

全部的異常類是從 java.lang.Exception 類繼承的子類,異常可分爲運行時異常跟編譯異常。

  • 運行時異常(即 RuntimeException 及其之類的異常)

這類異常在代碼編寫的時候不會被編譯器所檢測出來,是能夠不須要被捕獲便可以不處理,可是咱們能夠編寫代碼處理(使用 try…catch…finally)這樣的異常。對於這些異常,咱們應該修正代碼,而不是去經過異常處理器處理,這樣的異常發生的緣由多半是代碼寫的有問題(通常的作法是進行判斷後處理)。

常見的 RUNtimeException 有:NullpointException(空指針異常)、ClassCastException(類型轉換異常)、IndexOutOfBoundsException(數組越界異常)等。

  • 編譯異常(RuntimeException 之外的異常)

這類異常在編譯時編譯器會提示須要捕獲,若是不進行捕獲則編譯錯誤。在方法中要麼用 try…catch 語句捕獲它並處理,要麼用 throws 子句聲明拋出它,不然編譯不會經過。這樣的異常通常是由程序的運行環境致使的。由於程序可能被運行在各類未知的環境下,而程序員沒法干預用戶如何使用他編寫的程序,因而程序員就應該爲這樣的異常時刻準備着。

常見編譯異常有:IOException(流傳輸異常)、SQLException(數據庫操做異常)等。

3.Java處理異常的機制

拋出異常以及捕獲異常 ,一個方法所能捕捉的異常,必定是 Java 代碼在某處所拋出的異常。簡單地說,異常老是先被拋出,後被捕捉的。

  • 拋出異常

在執行一個方法時,若是發生異常,則這個方法生成表明該異常的一個對象,中止當前執行路徑,並把異常對象提交給 JRE。

  • 捕獲異常

JRE 獲得異常後,尋找相應的代碼來處理該異常。JRE 在方法的調用棧中查找,從生成異常的方法開始回溯,直到找到相應的異常處理代碼爲止。

  • 五個關鍵字:try、catch、finally、throws、throw。

 

640?wx_fmt=png

 

 

異常處理是經過 try…catch…finally 語句實現的。代碼結構以下。

try{
    ......    //可能產生異常的代碼}catch( ExceptionName1 e ){
    ......    //當產生ExceptionName1型異常時的處置措施}catch( ExceptionName2 e ){
    ......     //當產生ExceptionName2型異常時的處置措施}  
[ finally{
   ......     //不管是否發生異常,都無條件執行的語句
 }  ]

 

五、異常處理對項目質量的影響

 

若是一個項目裏的各個功能在異常處理方面下的功夫不夠,勢必會極大地影響項目的質量。

下面我列舉幾個例子,供你們參考。

1.空指針異常。

我見過5年開發經驗的程序員對空指針竟然不作任何處理,空指針的處理是 Java 程序員的基本功,若是連這個都處理不了,真的不能算是合格的 Java 程序員。

空指針的處理很簡單,就是在使用一個對象的時候,記得加一層非空判斷就ok了,代碼以下所示。

if (list != null && list.size() > 0) {
    user = list.get(0);
}

2.網絡超時異常。

在實際開發項目中,會使用到不少接口服務,好比 WebService 或者 HTTP 接口,這些服務的調用頗有可能會致使網絡超時等異常,只要發生超時異常,若是不進行處理的話,勢必會影響所涉及的功能,進而影響項目質量。

網絡超時異常,通常會設置接口超時時間,若是超時了,開發測試過程當中去優化服務提供方的代碼,看看是否是有不合理的查詢或者低效率的查詢。做爲服務調用方來講,接口超時後,通常會進行接口重發調用,若是接口提供方提供了服務執行結果查詢接口的話,那麼服務調用方應該在超時處理時,先調用服務執行結果查詢接口,根據查詢的結果再來肯定是否要從新發起服務調用。網絡超時處理機制以下圖所示。

 

640?wx_fmt=png

3.友好的用戶體驗。

若是後臺程序出現異常後,不作任何處理,直接把異常堆棧顯示到用戶界面裏,這種項目的質量是極其差的,尤爲是剛作項目的新人要特別注意。

用戶體驗還包括用戶的輸入項,及時作校驗,及時提醒給用戶,除了在前端界面使用 JavaScript 校驗外,提交到後端的信息也要再作一次校驗,防止程序提交。

4.異常處理與日誌打印。

異常處理的同時必定要配合日誌使用,用日誌記錄下來4個 W:What、Where、When、Why,即什麼出了錯(或者錯誤是什麼),哪裏出了錯,什麼時間出的錯,錯誤產生的緣由。

若是有異常處理,可是沒有日誌記錄,那麼咱們遇到問題,反查的時候就很棘手,無從下手。記錄日誌通常用 log4j,把日誌記錄到特定的文件裏,而不建議使用 e.printStackTrace() 打印堆棧。

另外最不可取的就是程序代碼 catch 了異常,catch 塊裏什麼都沒寫。這樣功能發生異常後,咱們根本沒法察覺。以下代碼所示。

try{    Do something
}catch(Exception e){   //此處無任何代碼(最不可取的代碼)}

下面咱們舉個小例子,來看下 Java 代碼,如何合理地處理異常。一個推薦的異常處理實例,以下面代碼所示:

 

640?wx_fmt=png

在最外層調用處,處理 ServiceException,打印堆棧信息,並轉化成友好的提示信息 message 返回給用戶界面,請見下面代碼。

catch (ServiceException e) {
    LOGGER.error("根據姓名查詢用戶失敗" + e.toString());
    message = "根據姓名查詢用戶失敗,姓名爲:" + userName;
}

 

六、異常處理對工資待遇的影響

 

一個程序員的異常處理能力的高低與項目質量的高低緊密相連。所以,一個優秀的程序員,不只要能完成項目需求和功能,還需對業務邏輯的異常處理要專業。

有的程序員寫的代碼只能在正常環境下,正常流程下,程序能夠正常執行。凡是稍微與預約的流程不吻合,程序就會出現各類問題,致使程序的功能沒法使用。也就是說,程序員在完成業務功能的同時,沒有考慮清楚邊界。

在項目開發中,一個優秀的程序員和一個新手的區別就是對業務的理解,而後業務轉化成代碼,而且能考慮各類異常流程和優良的用戶體驗。

若是能作到在項目中對異常的合理和全面地處理,那麼就有理由要求提升本身的工資待遇(能夠提升20-30%),由於只有優秀的程序員才能作到面面俱到。

但願你們輕鬆掌握Java異常處理,而且能夠運用到項目中。

 

 

640?wx_fmt=png

 

640?wx_fmt=jpeg

相關文章
相關標籤/搜索