Java把異常做爲一種類,當作對象來處理。全部異常類的基類是Throwable類,兩大子類分別是Error和Exception。html
系統錯誤由Java虛擬機拋出,用Error類表示。Error類描述的是內部系統錯誤,例如Java虛擬機崩潰。這種狀況僅憑程序自身是沒法處理的,在程序中也不會對Error異常進行捕捉和拋出。java
異常(Exception)又分爲RuntimeException(運行時異常)和CheckedException(檢查時異常),二者區別以下:數組
CheckedException:編譯期間能夠檢查到的異常,必須顯式的進行處理(捕獲或者拋出到上一層)。例如:IOException, FileNotFoundException等等。服務器
一、簡單的:網絡
二、複雜的:socket
首先說明一點,java中的Exception類的子類不只僅只是像上圖所示只包含IOException和RuntimeException這兩大類,事實上Exception的子類不少不少,主要可歸納爲:運行時異常與非運行時異常。post
一java異常體系結構url
從上述圖示能夠看到,spa
Thorwable類(表示可拋出)是全部異常和錯誤的超類,兩個直接子類爲Error和Exception,分別表示錯誤和異常。其中異常類Exception又分爲運行時異常(RuntimeException)和非運行時異常, 這兩種異常有很大的區別,也稱之爲不檢查異常(Unchecked Exception)和檢查異常(Checked Exception)。下面將詳細講述這些異常之間的區別與聯繫:線程
一、Error與Exception
Error是程序沒法處理的錯誤,它是由JVM產生和拋出的,好比OutOfMemoryError、ThreadDeath等。這些異常發生時,Java虛擬機(JVM)通常會選擇線程終止。
Exception是程序自己能夠處理的異常,這種異常分兩大類運行時異常和非運行時異常。程序中應當儘量去處理這些異常。
二、運行時異常和非運行時異常
運行時異常都是RuntimeException類及其子類異常,如NullPointerException、IndexOutOfBoundsException等,這些異常是不檢查異常,程序中能夠選擇捕獲處理,也能夠不處理。這些異常通常是由程序邏輯錯誤引發的,程序應該從邏輯角度儘量避免這類異常的發生。
非運行時異常是RuntimeException之外的異常,類型上都屬於Exception類及其子類。從程序語法角度講是必須進行處理的異常,若是不處理,程序就不能編譯經過。如IOException、SQLException等以及用戶自定義的Exception異常,通常狀況下不自定義檢查異常。
經常使用關鍵字:try、catch、throw(拋出一個異常,動詞)、throws(聲明一個方法可能拋出的異常)、finally。
若方法中存在檢查時異常,若是不對其捕獲,那必須在方法頭中顯式聲明該異常,以便於告知方法調用者此方法有異常,須要進行處理。
在方法中聲明一個異常,方法頭中使用關鍵字throws,後面接上要聲明的異常。若聲明多個異常,則使用逗號分割。
如果父類的方法沒有聲明異常,則子類繼承方法後,也不能聲明異常。
若執行try塊的過程當中沒有發生異常,則跳過catch子句。如果出現異常,try塊中剩餘語句再也不執行。開始逐步檢查catch塊,判斷catch塊的異常類實例是不是捕獲的異常類型。匹配後執行相應的catch塊中的代碼。若是異常沒有在當前的方法中被捕獲,就會被傳遞給該方法的調用者。這個過程一直重複,直到異常被捕獲或被傳給main方法(交給JVM來捕獲)。
對於try..catch捕獲異常的形式來講,對於異常的捕獲,能夠有多個catch。對於try裏面發生的異常,他會根據發生的異常和catch裏面的進行匹配(按照catch塊從上往下匹配),若是有匹配的catch,它就會忽略掉這個catch後面全部的catch。
若是有finally的話進入到finally裏面繼續執行。
try ctach fianally 中有return 時,會先執行return ,可是不會返回。在執行完 finally 後 進行返回。
return 的是基本類型數據時, fianlly 裏面的語句不會影響 return 的值,
return 的是引用類型數據時,此時已經肯定了要返回對象的地址(地址一),後面 fianlly 裏面的能夠經過修改前面地址一中的內容修改返回的內容,
可是若是將對象指向另外一個地址(地址二),則不會影響返回的內容。由於返回的對象地址已經肯定爲地址一,只能經過修改地址一對象的內容修改返回的信息。
二異常的捕獲和處理
異常處理的步驟:
throw try catch finally throws下面是在網絡通訊中運用socket的一段代碼:
try { mSocket=new Socket(ip,port); if(mSocket!=null) { Log.i("Client","socket is create"); clientInput=new ClientInputThread(mSocket); clientOutput=new ClientOutputThread(mSocket); clientInput.setStart(true); clientOutput.setStart(true); clientInput.start(); clientOutput.start(); } else { Log.i("Client","socket is not create"); // Toast.makeText(, "親,服務器端鏈接出錯",0).show(); } } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{}
從上述代碼能夠看到異常處理的步驟爲
二、 try、catch、finally三個語句塊應注意的問題
第一:try、catch、finally三個語句塊均不能單獨使用,三者能夠組成 try...catch...finally、try...catch、try...finally三種結構,catch語句能夠有一個或多個,finally語句最多一個。
第二:try、catch、finally三個代碼塊中變量的做用域爲代碼塊內部,分別獨立而不能相互訪問。若是要在三個塊中均可以訪問,則須要將變量定義到這些塊的外面。
第三:多個catch塊時候,最多隻會匹配其中一個異常類且只會執行該catch塊代碼,而不會再執行其它的catch塊,且匹配catch語句的順序爲從上到下,也可能全部的catch都沒執行。
第四:先Catch子類異常再Catch父類異常。
用示意圖表示以下:
三、throw、throws關鍵字
throw關鍵字是用於方法體內部,用來拋出一個Throwable類型的異常。若是拋出了檢查異常,則還應該在方法頭部聲明方法可能拋出的異常類型。該方法的調用者也必須檢查處理拋出的異常。若是全部方法都層層上拋獲取的異常,最終JVM會進行處理,處理也很簡單,就是打印異常消息和堆棧信息。throw關鍵字用法以下:
public static void test() throws Exception { throw new Exception("方法test中的Exception"); }
throws關鍵字用於方法體外部的方法聲明部分,用來聲明方法可能會拋出某些異常。僅當拋出了檢查異常,該方法的調用者才必須處理或者從新拋出該異常。當方法的調用者無力處理該異常的時候,應該繼續拋出.
注意一個方法throws出某個異常可是該方法內部能夠不throw出該異常,代碼以下:
class ER extends RuntimeException { } class SomeClass { public void fun()throws ER { System.out.println("AAAA"); } } public class ExceptionTest { public static void main(String[] args) { // TODO Auto-generated method stub SomeClass A=new SomeClass(); A.fun(); } }
程序運行結果以下:AAAA。
參考:Java 異常體系
參考:java異常體系結構詳解