Java編程基礎-異常__演算法

來源:互聯網
上載者:User
一、異常 1、什麼是異常         在java中,程式在運行時出現的不正常情況稱為異常,以異常類的形式對這些非正常情況進行封裝,通過異常處理機制對程式運行時發生的各種問題進行處理。其實就是java對不正常情況進行描述後的對象體現。
2、java異常類 

         在java中提供了大量的異常類,查閱API文檔,Throwable 類是 Java 語言中所有錯誤或異常的超類。只有當對象是此類(或其子類之一)的執行個體時,才能通過 JAVA 虛擬機器或者 Java throw 語句拋出。類似地,只有此類或其子類之一才可以是 catch 子句中的參數類型。

        Throwable有兩個直接的子類Error和Exception,其中,Error代表程式中產生的錯誤,Exception代表程式中產生的異常。

       a)    Error類稱為錯誤類,它表示java運行時產生的系統內部錯誤或資源耗盡的錯誤,是比較嚴重的,僅靠修改程式本身是不能恢複執行的。對於Error一般不編寫針對性的代碼對其進行處理。
       b)    Exception類稱為異常類,它表示程式本身可以處理的錯誤,在java開發程式中進行的異常處理,都是針對Exception類及其子類。在Exception類的眾多子類中有一個特殊的RuntimeException類,該類及其子類用於表示運行時異常,除了此類,Exception類下所有其它的子類都用於表示編譯時間異常。對於Exception可以採用針對性的代碼對其進行處理。


3、Throwable常用方法

String getMessage()   :返回此throwable的詳細訊息字串

void printStackTrace()   :將此throwable及其追蹤輸出至標準錯誤流
void printStackTrace(PrintStream s)   :將此throwable及其追蹤輸出到指定的輸出資料流


4、常見異常 RuntimeException子類:

a) java.lang.ArrayIndexOutOfBoundsException

    數組下標越界異常。當對數組的索引值為負數或大於等於數組大小時拋出。

b)java.lang.ArithmeticException
    算術條件異常。比如:整數除零等。

c)java.lang.NullPointerException
    null 指標異常。當應用試圖在要求使用對象的地方使用了null時,拋出該異常。比如:調用null對象的執行個體方法、訪問null對象的屬性、計算null對象的長度、使用throw語句拋出null等等
 d)java.lang.ClassNotFoundException
    找不到類異常。當應用試圖根據字串形式的類名構造類,而在遍曆CLASSPAH之後找不到對應名稱的class檔案時,拋出該異常。
e)java.lang.NegativeArraySizeException  數組長度為負異常

 f)java.lang.IllegalArgumentException 非法參數異常

IOException a)IOException:操作輸入資料流和輸出資料流時可能出現的異常。
b)FileNotFoundException   檔案未找到異常

其他 a)ClassCastException    類型轉換異常類
b)SQLException   操作資料庫異常類
c)NoSuchFieldException   欄位未找到異常
d)NoSuchMethodException   方法未找到拋出的異常
e)NumberFormatException    字串轉換為數字拋出的異常
f)StringIndexOutOfBoundsException 字串索引超出範圍拋出的異常
g)IllegalAccessException  不允許訪問某類異常



二、運行時異常和編譯時間異常

        異常可以分為編譯時間被檢測異常(該異常在編譯時間,如果沒有處理(沒有拋也沒有try),編譯失敗。)和編譯時間不被檢測的異常(運行時異常RuntimeException及其子類。在編譯時間,不需要處理,編譯器不檢查。)
 1、編譯時間異常(也稱checked異常)

        編譯時間異常的特點是java編譯器會對其進行檢查,如果出現異常就必須對異常進行處理,否則程式無法通過編譯。處理方式有兩種:一是使用try..catch語句對異常進行捕獲;二是使用throws關鍵字聲明拋出異常,讓調用者對其處理。
2、運行時異常(也稱unchecked異常)

        特點是java編譯器不會對其進行檢查,當程式中出現這類異常時,即時沒有捕獲或拋出處理,編譯也能通過。運行時異常一般是由於程式中的邏輯錯誤引起的,在程式運行時無法恢複。



三、異常處理機制

在java應用程式中,對異常的處理要麼拋出異常,要麼捕獲異常。 捕獲異常  1、 在Java中,異常通過try-catch語句捕獲。其一般文法形式為:

       try {
            // 可能發生異常的程式碼
        } catch (ExceptionType1 e) {
            // 捕獲並處置try拋出的異常類型Type1
        } catch (ExceptionType2 e) {
            // 捕獲並處置try拋出的異常類型Type2
        }


         異常捕獲處理過程:關鍵詞try後的一對大括弧將一塊可能發生異常的程式碼封裝起來,稱為監控地區。Java方法在運行過程中出現異常,則建立異常對象。將異常拋出監控地區之外,由Java運行時系統試圖尋找匹配的catch子句以捕獲異常。catch語句帶一個Throwable類型的參數, 表示可捕獲異常類型。當try中出現異常時,catch會捕獲到發生的異常,並和自己的異常類型匹配, 若匹配,則執行catch塊中代碼,並將catch塊參數指向所拋的異常對象。catch語句可以有多個, 用來匹配多個中的一個異常,一旦匹配上後則運行其異常處理代碼,try-catch語句結束。
匹配的原則是:如果拋出的異常對象屬於catch子句的異常類,或者屬於該異常類的子類,則認為產生的異常對象與catch塊捕獲的異常類型相匹配。


2、樣本示範:

數學上我們都知道除法中被除數不能為0,我們以此為例。

首先,示範不作任何處理時的情況。

public class TestException {public static void main(String[] args) {int x = 5;int y = 0;// 除數為0System.out.println(x / y);}}
運行結果為:

Exception in thread "main" java.lang.ArithmeticException: / by zero
at test.TestException.main(TestException.java:8)

系統報了個ArithmeticException: / by zero 算術異常,並且指出是被0除


其次:我們示範捕捉throw語句拋出的除數為0的異常並處理。

public class TestException {public static void main(String[] args) {int x = 5;int y = 0;// 除數為0try {//監控地區if (y == 0) {throw new ArithmeticException();//通過throw語句拋出異常}System.out.println(x / y);} catch (ArithmeticException e) {//捕捉異常System.out.println("程式出現異常,除數不能為0");}}}
運行結果為:

程式出現異常,除數不能為0


        簡單分析:在try監控地區通過if語句進行判斷,當“除數為0”的錯誤條件成立時引發ArithmeticException異常,建立 ArithmeticException異常對象,並由throw語句將異常拋給Java運行時系統,由系統尋找匹配的異常處理器catch並運行相應異常處理代碼,列印輸出“程式出現異常,除數不能為0”,try-catch語句結束,繼續程式流程。實際上,“除數為0”等ArithmeticException,是RuntimException的子類。而運行時異常將由運行時系統自動拋出,不需要使用throw語句。


最後,我們測試捕捉運行時系統自動拋出“除數為0”引發的ArithmeticException異常。

public class TestException {public static void main(String[] args) {int x = 5;int y = 0;// 除數為0try {System.out.println(x / y);} catch (ArithmeticException e) {//捕捉異常System.out.println("程式出現異常,除數不能為0");}}}

運行結果為:

程式出現異常,除數不能為0


        簡單分析:在運行中出現“除數為0”錯誤,引發ArithmeticException異常。運行時系統建立異常對象並拋出監控地區,轉而匹配合適的異常處理器catch,並執行相應的異常處理代碼。由於檢查運行時異常的代價遠大於捕捉異常所帶來的益處,運行時異常不可查。Java編譯器允許忽略運行時異常,一個方法可以既不捕捉,也不聲明拋出運行時異常。


        注意:一旦某個catch捕獲到匹配的異常類型,將進入異常處理代碼。一經處理結束,就意味著整個try-catch語句結束。其他的catch子句不再有匹配和捕獲異常類型的機會。而對於有多個catch子句的異常程式而言,應該盡量將捕獲的子類異常的catch子句放在前面,同時盡量將捕獲相對高層的父類異常的catch子句放在後面。否則,捕獲底層的子類異常的catch子句將可能會被屏蔽。
RuntimeException異常類包括運行時各種常見的異常,RuntimeException異常類的catch子句應該放在最後面,否則可能會屏蔽其後的特定異常處理或引起編譯錯誤。



3、try-catch語句還可以包括第三部分,就是finally子句。它表示無論是否出現異常,都應當執行的內容。

try-catch-finally語句的一般文法形式為:
       try {
            // 可能發生異常的程式碼
        } catch (ExceptionType1 e) {
            // 捕獲並處置try拋出的異常類型Type1
        } catch (ExceptionType2 e) {
            // 捕獲並處置try拋出的異常類型Type2
        }finally{
            //無論是否發生異常,都將執行的語句塊
        }

       finally 塊:無論是否捕獲或處理異常,finally塊裡的語句都會被執行。當在try塊或catch塊中遇到return語句時,finally語句塊將在方法返回之前被執行。在以下4種特殊情況下,finally塊不會被執行:
1)在finally語句塊中發生了異常。
2)在前面的代碼中用了System.exit()退出程式。
3)程式所在的線程死亡。
4)關閉CPU。

程式碼範例:

public class TestException {public static void main(String[] args) {try {int result = divide(4, 0);// 調用divide()方法// int result = divide(4, 2);//測試未發生異常情況System.out.println(result);} catch (Exception e) {System.out.println("捕獲的異常資訊為" + e.getMessage());} finally {System.out.println("進入finally代碼塊");}System.out.println("程式繼續向下執行");}public static int divide(int x, int y)// 定義一個兩個整數相除的方法{int result = x / y;// 定義一個變數result記住相除的結果return result;// 將結果返回}}
運行結果為:

捕獲的異常資訊為/ by zero
進入finally代碼塊
程式繼續向下執行

未發生異常測試結果為:

2
進入finally代碼塊
程式繼續向下執行

try、catch、finally三個語句塊應注意的問題: 
a)try、catch、finally三個語句塊均不能單獨使用,三者可以組成 try...catch...finally、try...catch、 try...finally三種結構,catch語句可以有一個或多個,finally語句最多一個。 

b)try、catch、finally三個代碼塊中變數的範圍為代碼塊內部,分別獨立而不能相互訪問。 如果要在三個塊中都可以訪問,則需要將變數定義到這些塊的外面。 
c)多個catch塊時候,只會匹配其中一個異常類並執行catch塊代碼,而不會再執行別的catch塊, 並且匹配catch語句的順序是由上到下。

d)必須遵循語句塊放置順序try-catch-finally的順序。

e)可嵌套 try-catch-finally 結構。比如,try中還可以有try..catch處理


拋出異常 4、throws拋出異常

       如果一個方法可能會出現異常,但沒有能力處理這種異常,可以在方法聲明處用throws子句來聲明拋出異常。例如汽車在運行時可能會出現故障,汽車本身沒辦法處理這個故障,那就讓開車的人來處理。throws語句用在方法定義時聲明該方法要拋出的異常類型,如果拋出的是Exception異常類型,則該方法被聲明為拋出所有的異常。多個異常可使用逗號分割。throws語句的文法格式為:

methodName([param1,param2,..])throws ExceptionType1[,ExceptionType2..]{}
        throws關鍵字需要寫在方法聲明的後面,throws後面需要聲明方法中發生異常的類型,通常將這種做法稱為方法聲明拋出一個異常。 使用throws關鍵字將異常拋給調用者後,如果調用者不想處理該異常,可以繼續向上拋出,但最終要有能夠處理該異常的調用者。

程式碼範例:

public class TestException {public static void main(String[] args) {try {int result = divide(4, 0);System.out.println(result);} catch (ArithmeticException e) {System.out.println("捕獲的異常資訊為" + e.getMessage());} finally {System.out.println("進入finally代碼塊");}System.out.println("程式繼續向下執行");}public static int divide(int x, int y) throws ArithmeticException// 拋出異常{int result = x / y;return result;}}

throws拋出異常規則: a) 如果是運行時異常,那麼可以不使用throws關鍵字來聲明要拋出的異常,編譯仍能順利通過,但在運行時會被系統拋出。
b)如果是編譯時間異常,要麼用try-catch語句捕獲,要麼用throws子句聲明將它拋出,否則會導致編譯錯誤

c)僅當拋出了異常,該方法的調用者才必須處理或者重新拋出該異常。當方法的調用者無力處理該異常的時候,應該繼續拋出。


5、使用throw拋出異常

        throw總是出現在函數體內,用來拋出一個Throwable類型的異常。程式會在throw語句後立即終止,它後面的語句執行不到,然後在包含它的所有try塊中(可能在上層調用函數中)從裡向外尋找含有與其匹配的catch子句的try塊。 由於異常是異常類的執行個體對象,我們可以建立異常類的執行個體對象通過throw語句拋出。該語句的文法格式為:
throw new ExceptionType();

程式碼範例:

public class MyException extends Exception {// 建立自訂異常類private String message;// 定義String類型變數private int value;// 定義int類型變數public MyException() {super();}public MyException(String message, int value) {this.message = message;this.value = value;}public int getValue() {return value;}public String getMessage() {return message;}}
測試:
public class TestMyException {public static void main(String[] args) {try {// 包含可能發生異常的語句int result = divide(4, -1);// 調用divide()方法System.out.println(result);} catch (MyException e) {// 處理自訂異常System.out.println(e.getMessage());// 輸出異常資訊System.out.println("錯誤的負數是:" + e.getValue());// 輸出異常值} catch (ArithmeticException e) { // 處理ArithmeticException異常System.out.println("除數不能為0"); // 輸出提示資訊} catch (Exception e) { // 處理其他異常System.out.println("程式發生了其他的異常"); // 輸出提示資訊}System.out.println("over");}public static int divide(int x, int y) throws MyException// 定義方法拋出{if (y < 0) {// 判斷參數是否小於0throw new MyException("出現了除數是負數的情況。------/by FuShu", y);// 異常資訊}return x / y;// 傳回值}}
運行結果為:

出現了除數是負數的情況。------/by FuShu
錯誤的負數是:-1
over

throws和throw的區別:
a)throws使用在函數上。throw使用在函數內。
b)throws後面跟的是異常類,可以跟多個,用逗號隔開。throw後面跟的是異常對象。


四、自訂異常

        因為實際項目中會出現特有的問題,而這些問題並未被java所描述並封裝對象。所以對於這些特有的問題可以按照java對問題的封裝思想。將特有的問題,進行自訂的異常封裝。在java中允許使用者自訂異常,自訂異常步驟:
(1)、建立自訂異常類,且該類必須繼承自Exception或其子類。(因為異常體系有一個特點,因為異常類和異常對象都被拋出。他們都具備可拋性,這個可拋性是Throwable這個體系中的專屬特點。)
(2)、在方法中通過throw關鍵字拋出異常對象。
(3)、如果在當前拋出異常的方法中處理異常,可以使用try-catch語句捕獲並處理;否則在方法的聲明處通過throws關鍵字指明要拋出給方法調用者的異常,繼續進行下一步操作。
(4)、在出現異常方法的調用者中捕獲並處理異常。

自訂異常可參見上面使用throw拋出異常的程式碼範例。

 異常在子父類覆蓋中的體現:
(1)、子類在覆蓋父類時,如果父類的拋出方法異常,那麼子類的覆蓋方法,只能拋出父類的異常或該異常的子類
(2)、如果父類方法中拋出多個異常,那麼子類在覆蓋該方法時,只能拋出父類異常的子集。
(3)、如果父類或介面的方法中沒有異常拋出,那麼子類在覆蓋方法時,也不可以拋出異常。如果子類方法發生了異常,就必須要進行try處理,絕對不能拋。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.