代碼的世界和現實世界同樣,不會一路順風,起碼不會像咱們想象中的那麼順利。寫代碼的是人,人的思惟存在侷限性,這種侷限性,體如今代碼中,就是漏洞。假若一段程序在生產環境中崩潰,勢必讓人十分惱火。這種讓人頭大的狀況就是異常的一種。html
Java 是這樣定義異常的:java
異常指的是,那些在程序運行過程當中,中斷正常的指令流程的事件。
實際上,異常還會在如下場景中發生:程序員
而咱們並不但願程序由於上述狀況掛掉,而是但願程序可以在遇到異常時,巧妙地處理以後,繼續運行下去。oracle
所幸,Java 提供了一套機制,用於在程序程序出錯(出現異常)時,進行:編碼
亦即:異常處理機制。顧名思義,該機制用於對程序運行中不正常的狀況進行處理。
簡單來講,Java 中的異常處理是:當異常發生時,運行時系統逆着方法的調用棧(call stack)去尋找可以處理這種異常的東西。spa
以一個把字符串轉換成整數的方法爲例:設計
public Integer stringToNumber(String strToFormat){ Integer targetNum; try{ targetNum = new Integer(strToFormat); }catch(NumberFormatException e){ targetNum = DEFAULT_NUM; } return targetNum; }
在上述代碼中,當 strToFormat 不能轉化成一個整形數時,就轉化成一個默認的值。NumberFormatException
發生時,方法當即終止。控制權被交由 catch 代碼塊,也就是異常處理器(exception hanlder)。代碼雖然簡單,卻包含了 Java 異常處理的通常步驟。code
在 Java 中,全部的異常派生於 Throwable 接口。這些異常,又被分爲 Error 和 Exception。這兩類異常,又衍生了一些子類。下面的圖片,描述了 Java 的異常體系圖:orm
不過,咱們應當把精力放在 RuntimeException 上,由於「全部的運行時異常,都是程序員的問題」。這類異常,又被叫作未檢查異常,一般交由 JVM 處理。相對應的,那些咱們知道可能會出現問題、,被叫作已檢查的異常。這類異常須要開發者手動向上級拋出,直到 JVM 級別,或者在調用方法時使用 try-catch
處理。htm
通常來講,在寫一個方法時,要儘量聲明全部已檢查異常,經過內部邏輯控制,避免未檢查(運行時)異常。
在編碼過程當中,若是方法的檢查異常被精心設計,那麼咱們只管拋出異常便可。可是,一旦調用方法的地方沒有對這種可能出現的異常進行處理,那麼程序就會終止。因此,要對異常進行捕獲操做,正如以前的字符串轉數字的方法同樣。
根據經驗,程序中應該捕獲那些知道如何處理的異常,把「職責」外的異常,交給方法的調用者去處理。下面是一個異常捕獲流程的示例代碼:
modifier returnType someMethod(type1 param1, type2 param2) throws Exception1, Exceptio2{ try{ ① // 某些操做 return returnType value; }catch(Exceptionx | Exceptiony e){ ② // 處理異常 }catch(Excpetion1 e1){ ③ throw new Excption1(e1); }catch(Exception e2){ ④ throw e2; }finally{ ⑤ // 一些操做 return returnType mockValue; } }
在上述代碼中,① 中進行操做,捕獲了 Exeptionx 或者 Exceptiony 時,② 進行異常處理;捕獲了 Exception1 時, ③ 把該異常包裝;捕獲了 Exception 2 時,④ 直接拋出異常;不管有無異常發生,⑤ 都會執行。
上面的代碼還有一個問題,就是 finally 代碼中包含返回值。有如下規則:
try
塊處理的儘可能用一個,而後按層次捕獲異常,下面的代碼是被建議的:try{ // 某些操做 }catch(SomeException1 e1){ // 異常 1 的處理 }catch(SomeException2 e2){ // 異常 2 的處理 }
NumberFormatException
轉化成自定義的異常