1、java中異常的分類:java
1.Error數據庫
當程序發生不可控的錯誤時,一般作法是通知用戶並停止程序的執行。與異常不一樣的是Error及其子類的對象不該被拋出。數組
Error是throwable的子類,表明編譯時間和系統錯誤,用於指示合理的應用程序不該該試圖捕獲的嚴重問題。安全
Error由Java虛擬機生成並拋出,包括動態連接失敗,虛擬機錯誤等。程序對其不作處理。網絡
2.Exceptionjvm
Exception通常分爲Checked異常和Runtime異常,全部RuntimeException類及其子類的實例被稱爲Runtime異常,不屬於該範疇的異常則被稱爲CheckedException。spa
①Checked異常(除RuntimeException以外的其餘異常)設計
只有java語言提供了Checked異常,Java認爲Checked異常都是能夠被處理的異常,因此Java程序必須顯示處理Checked異常。若是程序沒有處理Checked異常,該程序在編譯時就會發生錯誤沒法編譯。這體現了Java的設計哲學:沒有完善錯誤處理的代碼根本沒有機會被執行。對Checked異常處理方法有兩種指針
1 當前方法知道如何處理該異常,則用try...catch塊來處理該異常。
2 當前方法不知道如何處理,則在定義該方法是聲明拋出該異常。orm
②RuntimeException
Runtime如除數是0和數組下標越界等,其產生頻繁,處理麻煩,若顯示申明或者捕獲將會對程序的可讀性和運行效率影響很大。因此由系統自動檢測並將它們交給缺省的異常處理程序。固然若是你有處理要求也能夠顯示捕獲它們。
注意:異常和錯誤的區別:異常能被程序自己能夠處理,錯誤是沒法處理
2、Java異常機制主要依賴於try、catch、finally、throw、throws五個關鍵字。
1.try:它裏面放置可能引起異常的代碼
2.catch:後面對應異常類型和一個代碼塊,用於代表該catch塊用於處理這種類型的代碼塊,能夠有多個catch塊。
3.finally:主要用於回收在try塊裏打開的物力資源(如數據庫鏈接、網絡鏈接和磁盤文件),異常機制老是保證finally塊老是被執行。只有finally塊,執行完成以後,纔會回來執行try或者catch塊中的return或者throw語句,若是finally中使用了return或者 throw等終止方法的語句,則就不會跳回執行,直接中止。
4.throw:用於拋出一個實際的異常,能夠單獨做爲語句使用,拋出一個具體的異常對象。
5.throws:用在方法簽名中,用於聲明該方法可能拋出的異常。
異常的處理
在 Java 應用程序中,異常處理機制爲:拋出異常,捕捉異常。
拋出異常:當一個方法出現錯誤引起異常時,方法建立異常對象並交付運行時系統,異常對象中包含了異常類型和異常出現時的程序狀態等異常信息。運行時系統負責尋找處置異常的代碼並執行。
捕獲異常:在方法拋出異常以後,運行時系統將轉爲尋找合適的異常處理器(exception handler)。潛在的異常處理器是異常發生時依次存留在調用棧中的方法的集合。當異常處理器所能處理的異常類型與方法拋出的異常類型相符時,即爲合適 的異常處理器。運行時系統從發生異常的方法開始,依次回查調用棧中的方法,直至找到含有合適異常處理器的方法並執行。當運行時系統遍歷調用棧而未找到合適 的異常處理器,則運行時系統終止。同時,意味着Java程序的終止。
對於運行時異常、錯誤或可查異常,Java技術所要求的異常處理方式有所不一樣。
因爲運行時異常的不可查性,爲了更合理、更容易地實現應用程序,Java規定,運行時異常將由Java運行時系統自動拋出,容許應用程序忽略運行時異常。
對於方法運行中可能出現的Error,當運行方法不欲捕捉時,Java容許該方法不作任何拋出聲明。由於,大多數Error異常屬於永遠不能被容許發生的情況,也屬於合理的應用程序不應捕捉的異常。
對於全部的可查異常,Java規定:一個方法必須捕捉,或者聲明拋出方法以外。也就是說,當一個方法選擇不捕捉可查異常時,它必須聲明將拋出異常。
可以捕捉異常的方法,須要提供相符類型的異常處理器。所捕捉的異常,多是因爲自身語句所引起並拋出的異常,也多是由某個調用的方法或者Java運行時 系統等拋出的異常。也就是說,一個方法所能捕捉的異常,必定是Java代碼在某處所拋出的異常。簡單地說,異常老是先被拋出,後被捕捉的。
任何Java代碼均可以拋出異常,如:本身編寫的代碼、來自Java開發環境包中代碼,或者Java運行時系統。不管是誰,均可以經過Java的throw語句拋出異常。
從方法中拋出的任何異常都必須使用throws子句。
捕捉異常經過try-catch語句或者try-catch-finally語句實現。
整體來講,Java規定:對於可查異常必須捕捉、或者聲明拋出。容許忽略不可查的RuntimeException和Error。
3、常見的異常
一、 java.lang.ArrayIndexOutOfBoundsException
數組索引越界異常。當對數組的索引值爲負數或大於等於數組大小時拋出。
二、java.lang.ArithmeticException
算術條件異常。譬如:整數除零等。
三、java.lang.NullPointerException
空指針異常。當應用試圖在要求使用對象的地方使用了null時,拋出該異常。譬如:調用null對象的實例方法、訪問null對象的屬性、計算null對象的長度、使用throw語句拋出null等等
四、java.lang.ClassNotFoundException
找不到類異常。當應用試圖根據字符串形式的類名構造類,而在遍歷CLASSPAH以後找不到對應名稱的class文件時,拋出該異常。
五、java.lang.NegativeArraySizeException 數組長度爲負異常
六、java.lang.ArrayStoreException 數組中包含不兼容的值拋出的異常
七、java.lang.SecurityException 安全性異常
八、java.lang.IllegalArgumentException 非法參數異常
IOException:操做輸入流和輸出流時可能出現的異常。
EOFException 文件已結束異常
FileNotFoundException 文件未找到異常
ClassCastException 類型轉換異常類
ArrayStoreException 數組中包含不兼容的值拋出的異常
SQLException 操做數據庫異常類
NoSuchFieldException 字段未找到異常
NoSuchMethodException 方法未找到拋出的異常
NumberFormatException 字符串轉換爲數字拋出的異常
StringIndexOutOfBoundsException 字符串索引超出範圍拋出的異常
IllegalAccessException 不容許訪問某類異常
InstantiationException 當應用程序試圖使用Class類中的newInstance()方法建立一個類的實例,而指定的類對象沒法被實例化時,拋出該異常。
4. 用戶自定義的異常
用戶自定義異常類,只需繼承Exception類便可,而後經過throw關鍵字拋出異常。
舉例實驗:
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";
return t;
} catch (Exception e) {
// result = "catch";
t = "catch";
return t;
} finally {
t = "finally";
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
首先程序執行try語句塊,把變量t賦值爲try,因爲沒有發現異常,接下來執行finally語句塊,把變量t賦值爲finally,而後return t,則t的值是finally,最後t的值就是finally,程序結果應該顯示finally,可是實際結果爲try。在try語句的return塊中,return 返回的引用變量(t 是引用類型)並非try語句外定義的引用變量t,而是系統從新定義了一個局部引用t’,這個引用指向了引用t對應的值,也就是try ,即便在finally語句中把引用t指向了值finally,由於return的返回引用已經不是t ,因此引用t的對應的值和try語句中的返回值無關了。
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";
return t;
} catch (Exception e) {
// result = "catch";
t = "catch";
return t;
} finally {
t = "finally";
return t;
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
咱們發現try語句中的return語句給忽略。可能jvm認爲一個方法裏面有兩個return語句並無太大的意義,因此try中的return語句給忽略了,直接起做用的是finally中的return語句,因此此次返回的是finally。
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";
Integer.parseInt(null);
return t;
} catch (Exception e) {
t = "catch";
return t;
} finally {
t = "finally";
// System.out.println(t);
// return t;
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
這裏面try語句裏面會拋出 java.lang.NumberFormatException,因此程序會先執行catch語句中的邏輯,t賦值爲catch,在執行return以前,會把返回值保存到一個臨時變量裏面t ',執行finally的邏輯,t賦值爲finally,可是返回值和t',因此變量t的值和返回值已經沒有關係了,返回的是catch
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";
Integer.parseInt(null);
return t;
} catch (Exception e) {
t = "catch";
return t;
} finally {
t = "finally";
return t;
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
這個和例2有點相似,因爲try語句裏面拋出異常,程序轉入catch語句塊,catch語句在執行return語句以前執行finally,而finally語句有return,則直接執行finally的語句值,返回finally
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";
Integer.parseInt(null);
return t;
} catch (Exception e) {
t = "catch";
Integer.parseInt(null);
return t;
} finally {
t = "finally";
//return t;
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
這個例子在catch語句塊添加了Integer.parser(null)語句,強制拋出了一個異常。而後finally語句塊裏面沒有return語句。繼續分析一下,因爲try語句拋出異常,程序進入catch語句塊,catch語句塊又拋出一個異常,說明catch語句要退出,則執行finally語句塊,對t進行賦值。而後catch語句塊裏面拋出異常。結果是拋出java.lang.NumberFormatException異常
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";
Integer.parseInt(null);
return t;
} catch (Exception e) {
t = "catch";
Integer.parseInt(null);
return t;
} finally {
t = "finally";
return t;
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
這個例子和上面例子中惟一不一樣的是,這個例子裏面finally 語句裏面有return語句塊。try catch中運行的邏輯和上面例子同樣,當catch語句塊裏面拋出異常以後,進入finally語句快,而後返回t。則程序忽略catch語句塊裏面拋出的異常信息,直接返回t對應的值 也就是finally。方法不會拋出異常
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";
Integer.parseInt(null);
return t;
} catch (NullPointerException e) {
t = "catch";
return t;
} finally {
t = "finally";
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
這個例子裏面catch語句裏面catch的是NPE異常,而不是java.lang.NumberFormatException異常,因此不會進入catch語句塊,直接進入finally語句塊,finally對s賦值以後,由try語句拋出java.lang.NumberFormatException異常。
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";
Integer.parseInt(null);
return t;
} catch (NullPointerException e) {
t = "catch";
return t;
} finally {
t = "finally";
return t;
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
和上面的例子中try catch的邏輯相同,try語句執行完成執行finally語句,finally賦值s 而且返回s ,最後程序結果返回finally
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";return t;
} catch (Exception e) {
t = "catch";
return t;
} finally {
t = "finally";
String.valueOf(null);
return t;
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
這個例子中,對finally語句中添加了String.valueOf(null), 強制拋出NPE異常。首先程序執行try語句,在返回執行,執行finally語句塊,finally語句拋出NPE異常,整個結果返回NPE異常。
下面看一個例子(例1),來說解java裏面中try、catch、finally的處理流程
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";
return t;
} catch (Exception e) {
// result = "catch";
t = "catch";
return t;
} finally {
t = "finally";
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
首先程序執行try語句塊,把變量t賦值爲try,因爲沒有發現異常,接下來執行finally語句塊,把變量t賦值爲finally,而後return t,則t的值是finally,最後t的值就是finally,程序結果應該顯示finally,可是實際結果爲try。經過字節碼,咱們發現,在try語句的return塊中,return 返回的引用變量(t 是引用類型)並非try語句外定義的引用變量t,而是系統從新定義了一個局部引用t’,這個引用指向了引用t對應的值,也就是try ,即便在finally語句中把引用t指向了值finally,由於return的返回引用已經不是t ,因此引用t的對應的值和try語句中的返回值無關了。
下面在看一個例子:(例2)
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";
return t;
} catch (Exception e) {
// result = "catch";
t = "catch";
return t;
} finally {
t = "finally";
return t;
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
這裏稍微修改了 第一段代碼,只是在finally語句塊裏面加入了 一個 return t 的表達式。
按照第一段代碼的解釋,先進行try{}語句,而後在return以前把當前的t的值try保存到一個變量t',而後執行finally語句塊,修改了變量t的值,在返回變量t。
這裏面有兩個return語句,可是程序到底返回的是try 仍是 finally。
咱們發現try語句中的return語句給忽略。可能jvm認爲一個方法裏面有兩個return語句並無太大的意義,因此try中的return語句給忽略了,直接起做用的是finally中的return語句,因此此次返回的是finally。
接下來在看看複雜一點的例子:(例3)
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";
Integer.parseInt(null);
return t;
} catch (Exception e) {
t = "catch";
return t;
} finally {
t = "finally";
// System.out.println(t);
// return t;
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
這裏面try語句裏面會拋出 java.lang.NumberFormatException,因此程序會先執行catch語句中的邏輯,t賦值爲catch,在執行return以前,會把返回值保存到一個臨時變量裏面t ',執行finally的邏輯,t賦值爲finally,可是返回值和t',因此變量t的值和返回值已經沒有關係了,返回的是catch
例4:
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";
Integer.parseInt(null);
return t;
} catch (Exception e) {
t = "catch";
return t;
} finally {
t = "finally";
return t;
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
這個和例2有點相似,因爲try語句裏面拋出異常,程序轉入catch語句塊,catch語句在執行return語句以前執行finally,而finally語句有return,則直接執行finally的語句值,返回finally
例5:
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";
Integer.parseInt(null);
return t;
} catch (Exception e) {
t = "catch";
Integer.parseInt(null);
return t;
} finally {
t = "finally";
//return t;
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
這個例子在catch語句塊添加了Integer.parser(null)語句,強制拋出了一個異常。而後finally語句塊裏面沒有return語句。繼續分析一下,因爲try語句拋出異常,程序進入catch語句塊,catch語句塊又拋出一個異常,說明catch語句要退出,則執行finally語句塊,對t進行賦值。而後catch語句塊裏面拋出異常。結果是拋出java.lang.NumberFormatException異常
例子6:
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";
Integer.parseInt(null);
return t;
} catch (Exception e) {
t = "catch";
Integer.parseInt(null);
return t;
} finally {
t = "finally";
return t;
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
這個例子和上面例子中惟一不一樣的是,這個例子裏面finally 語句裏面有return語句塊。try catch中運行的邏輯和上面例子同樣,當catch語句塊裏面拋出異常以後,進入finally語句快,而後返回t。則程序忽略catch語句塊裏面拋出的異常信息,直接返回t對應的值 也就是finally。方法不會拋出異常
例子7:
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";
Integer.parseInt(null);
return t;
} catch (NullPointerException e) {
t = "catch";
return t;
} finally {
t = "finally";
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
這個例子裏面catch語句裏面catch的是NPE異常,而不是java.lang.NumberFormatException異常,因此不會進入catch語句塊,直接進入finally語句塊,finally對s賦值以後,由try語句拋出java.lang.NumberFormatException異常。
例子8
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";
Integer.parseInt(null);
return t;
} catch (NullPointerException e) {
t = "catch";
return t;
} finally {
t = "finally";
return t;
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
和上面的例子中try catch的邏輯相同,try語句執行完成執行finally語句,finally賦值s 而且返回s ,最後程序結果返回finally
例子9:
public class TryCatchFinally {
@SuppressWarnings("finally")
public static final String test() {
String t = "";
try {
t = "try";return t;
} catch (Exception e) {
t = "catch";
return t;
} finally {
t = "finally";
String.valueOf(null);
return t;
}
}
public static void main(String[] args) {
System.out.print(TryCatchFinally.test());
}
}
這個例子中,對finally語句中添加了String.valueOf(null), 強制拋出NPE異常。首先程序執行try語句,在返回執行,執行finally語句塊,finally語句拋出NPE異常,整個結果返回NPE異常。
對以上全部的例子進行總結
1 try、catch、finally語句中,在若是try語句有return語句,則返回的以後當前try中變量此時對應的值,此後對變量作任何的修改,都不影響try中return的返回值
2 若是finally塊中有return 語句,則返回try或catch中的返回語句忽略。
3 若是finally塊中拋出異常,則整個try、catch、finally塊中拋出異常
4.不管try、catch、finally 中遇到throw拋出異常或者return都是表明程序到此終止執行,以外的代碼將不會被繼續執行。
5.異常都是先要拋出而後捕獲異常。
6.拋出的異常和catch的異常類型要匹配才能捕獲,不然往上拋出直至jvm捕獲拋出。
7.finally中沒有return和throw或者其餘異常拋出時候,纔會返回到try或者catch裏繼續執行。
因此使用try、catch、finally語句塊中須要注意的是
1 儘可能在try或者catch中使用return語句。經過finally塊中達到對try或者catch返回值修改是不可行的。
2 finally塊中避免使用return語句,由於finally塊中若是使用return語句,會顯示的消化掉try、catch塊中的異常信息,屏蔽了錯誤的發生
3 finally塊中避免再次拋出異常,不然整個包含try語句塊的方法回拋出異常,而且會消化掉try、catch塊中的異常