加入異常處理操做,會增長程序的容錯性,會減小程序由於某些情況的發生忽然退出的狀況。java
異常機制可使程序中的異常處理代碼和正常業務代碼分離,保證程序代碼更加優雅,並能夠提升程序的健壯性。程序員
五個關鍵詞:try、catch、finally、throw和throws數據庫
Java的異常能夠分爲兩種:Checked異常和Runtime異常。網絡
Checked異常都是能夠在編譯階段被處理的異常,因此它強制程序處理全部的Checked異常。spa
Checked異常要麼顯式聲明拋出;要麼顯式捕獲並處理它。code
而Runtime異常則無需處理。對象
Error爲錯誤,Exception爲異常。Exception中RuntimeException爲Runtime異常,其餘都爲Checked異常。接口
Checked異常至少存在兩大不便: ①對於程序中的Checked異常,java要求必須顯式捕獲並處理該異常或者顯式聲明拋出該異常; ②若是在方法中顯式的聲明拋出Check異常,將會致使方法簽名與異常耦合,若是該方法是重寫父類的方法,則該方法拋出的異常還會受到被重寫方法的所拋出異常的限制。資源
大部分時候推薦Runtime異常,而不使用Check異常。字符串
runtime異常優勢:正常代碼和錯誤處理代碼分離;保證程序具備較好健壯性;避免checked的繁瑣性。
checked異常優勢:能在編譯時體型程序員代碼可能存在的問題,體型程序員必須注意處理該異常。
if(用戶輸入不合法) { alert 輸入不合法 goto retry } else { 業務實現代碼 }
常見的代碼中若是單純使用if else語句實現錯誤處理機制,主要存在兩個缺點:
①沒法窮舉全部的異常狀況②錯誤處理代碼和業務實現代碼混雜。
異常處理機制的過程:
當程序運行出現意外狀況時,系統會自動生成一個Exception對象來通知程序。 能夠採用try...catch捕獲異常; 或者使用throws拋出異常到上一層,但目標仍是尋找catch來捕獲異常,若是一直沒有找到對應的catch塊,那麼異常就會一直向拋出,直處處於JVM層次時,JVM處理,JVM處理異常的方式是,打印異常的跟蹤棧信息,並終止運行(這就是通常程序遇到異常後自動結束的緣由)。
1.try...catch捕獲異常
try { 業務實現代碼 } catch (Exception e) { alert 輸入不合法 goto retry }
若是try塊裏的業務邏輯代碼出現異常,系統自動生成一個異常對象,該異常對象被提交給Java運行環境時,這個過程被稱爲拋出異常,此時Java運行環境尋找能處理該異常對象的catch塊,找到並交給catch塊處理成爲捕獲異常。
每次try之後,catch塊至多隻能運行一個。如圖,Exception放在最後,也是由於若是它在最前面,那麼它必將捕獲異常,而它的子類也就沒有用了;而放到最後,可以爲其子類增長了一個捕獲未知異常的功能。也即「先處理小異常,再處理大異常」。
異常處理的嵌套:在try塊、catch塊或finally塊中包含完整的異常處理流程的情形被稱爲異常處理的嵌套。一般沒有必要使用兩次以上的必要,會下降程序可讀性。
Java7新增的多異常捕獲:
①捕獲多種類型的異常時,多種異常類型之間用豎線(|)隔開。
②捕獲多種類型的異常時,異常變量有隱式的final修飾,以此程序不能對異常變量從新賦值。
如圖所示:
訪問異常信息:全部的異常對象都包含了以下幾個經常使用方法:
①getMessage():返回該異常的詳細描述字符串
②printStackTrance():將該異常的跟蹤棧信息輸出到標準錯誤輸出。
③printStackTrance(PrintStream s):將該異常的跟蹤棧信息輸出到指定輸出流。
④getStackTrance():返回該異常的跟蹤棧信息
2.finally回收資源
有些時候,程序在try塊裏打開了一些物力資源(例如數據庫鏈接、網絡鏈接和磁盤文件等),這些物力資源都必須顯示回收。
異常處理語法結構,只有try塊是必須的;catch和finally至少出現其中之一。
try { //return 在調用return之前會先調用finally塊,再調用return; //System.exit(1); 退出虛擬機,再也不執行finally塊 } finally { }
注意:一旦在finally塊中使用了return和throw語句,將會致使try塊、catch塊中的return、throw語句失效。
java7加強的自動關閉資源的try語句(隱式的finally塊):
它容許在try關鍵字後緊跟一對圓括號,圓括號裏能夠聲明、初始化一個或多個資源,此處的資源指的是那些必須在程序結束時顯式關閉的資源。
爲了保證try語句能夠正常關閉資源,這些資源實現類必須實現AutoCloseable(拋出了Exception)或Closeable接口(拋出了IOException),實現這兩個接口就必須實現close()方法。
java9再次加強了try語句塊:
再也不須要圓括號聲明,只須要自動關閉的資源有finally修飾或者是有效的final(effectively final)(雖然沒有final修飾,可是再也不對該變量從新賦值)。
3.使用throws聲明拋出異常
思路:當前方法不知道如何處理這種類型的異常,該異常應該由上一級使用者處理;若是main方法一不知道如何處理這種類型的異常,也可使用throws聲明拋出異常,該異常將交給JVM處理。
public void main(String []args) throws IOException { }
使用throws聲明拋出異常時有一個限制,就是重寫時「兩小」中的一條規則: ①子類方法聲明拋出的異常類型應該是父類方法聲明拋出的異常類型的子類或相同。 ②子類方法聲明拋出的異常不容許比父類方法聲明拋出的異常多。
4.使用throw拋出異常
當程序出現錯誤時,系統會自動拋出異常;除此以外,java也容許程序自行拋出異常,自行拋出異常使用throw語句來完成。
throw拋出的不是一個異常類,而是一個異常實例。
public class ThrowTest{ public static void main(String []args) { try { //調用聲明拋出Checked異常的方法,要麼顯式捕捉該異常,要麼在main方法中再次聲明拋出 throwChecked(-3); } catch(Exception e) { System.out.println(e.getMessage()); } //調用聲明拋出Runtime異常的方法既能夠顯式捕獲該異常,也能夠不理會該異常 throwRuntime(3); } public static void throwChecked(int a)throws Exception{ if(a>0) { //自行拋出Exception異常,該代碼必須處於try塊裏,或者處於帶throws聲明的方法裏 throw new Exception("a的值大於0,不符合要求"); } } public static void throwRuntime(int a) { if(a>0) { //自行拋出RuntimeException異常,既能夠顯式捕獲該異常, //也能夠徹底不理會該異常,把該異常交給方法處理器調用 throw new RuntimeException("a的值大於0,不符合要求"); } } }