16.Java異常

轉載請保留原文鏈接: http://dashidan.com/article/java/basic/16.html

16.Java異常

Java異常是Java提供的一種識別及響應錯誤的一致性機制.

① Java異常機制相關關鍵字

Java異常機制相關關鍵字有: trycatchfinallythrowthrows. 關鍵字解釋:

  • try 用於監聽. 將被監聽的代碼(可能拋出異常的代碼)放在try語句塊之內, 當try語句塊內發生異常時,異常就被拋出.

  • catch 用來捕獲try語句塊中發生的異常.

  • finally finally語句塊總是會被執行. 主要用於回收在try塊裏打開的物理資源(如文件, 網絡連接, 數據庫連接等).

finally語句中return

只有finally塊執行完成之後,纔會執行try或者catch塊中的return或者throw語句. 如果finally中使用了return或者throw等終止方法的語句,則就不會跳回執行,直接停止.

  • throw 用於拋出異常.

  • throws 用在方法簽名中,用於聲明該方法可能拋出的異常.

② Java異常框架

Java將可拋出(Throwable)的結構分爲三種類型:

  • 編譯異常(Checked Exception)

  • 運行時異常(RuntimeException)

  • 錯誤(Error)

Java異常框架繼承關係如圖:

1.Throwable

ThrowableJava語言中所有錯誤或異常的超類, 包含兩個子類:ErrorException.它們通常用於指示發生了異常情況.Throwable包含了其線程創建時線程執行堆棧的快照,提供了printStackTrace()等接口用於獲取堆棧跟蹤數據等信息.

2.運行時異常RuntimeException

RuntimeException是那些可能在Java虛擬機正常運行期間拋出的異常的超類, 簡稱運行時異常. RuntimeException及其子類都被稱爲運行時異常.

Java編譯器不會檢查運行時異常.當程序中可能出現這類異常時,倘若既"沒有通過throws聲明拋出它",也"沒有用try-catch語句捕獲它",還是會編譯通過.

雖然Java編譯器不會檢查運行時異常, 但是我們也可以通過throws進行聲明拋出, 也可以通過try-catch對它進行捕獲處理. 如果產生運行時異常,則需要通過修改代碼來進行避免.

例如:

  • 除數爲零時產生的ArithmeticException異常

  • 數組越界時產生的IndexOutOfBoundsException異常

  • fail-fail機制產生的ConcurrentModificationException異常等,都屬於運行時異常.

部分常用運行時異常說明
異常描述
ArithmeticException除數爲零異常
ArrayIndexOutOfBoundsException數組越界
ClassCastException對象轉型錯誤
IllegalArgumentException參數不合法
IndexOutOfBoundsException指示某排序索引(例如對數組、字符串或向量的排序)超出範圍
NegativeArraySizeException數組長度爲負值
NullPointerException空指針異常
NumberFormatException當應用程序試圖將字符串轉換成一種數值類型,但該字符串不能轉換爲適當格式時,拋出該異常.

3.編譯異常Exception

Exception類以及Exception的子類中除了"運行時異常"之外的其它子類都屬於被檢查異常. 此類異常,要麼通過throws進行聲明拋出,要麼通過try-catch進行捕獲處理,否則不能通過編譯.

部分常用編譯異常說明
異常描述
ClassNotFoundException應用程序試圖加載類時,找不到相應的類,拋出該異常.
FileNotFoundException文件不存在異常
ClassCastException對象轉型錯誤
InterruptedException一個線程被另一個線程中斷,拋出該異常.
NoSuchFieldException請求的變量不存在
NoSuchMethodException請求的方法不存在

4.Error

Error類及其子類統稱錯誤. 用於指示試圖捕獲的嚴重問題, 大多數這樣的錯誤都是異常條件. 和運行時異常一樣, 編譯器也不會檢查Error. 當資源不足、約束失敗、或是其它導致程序無法繼續運行的條件發生時, 就產生錯誤. 程序本身無法修復這些錯誤.

例:

  • VirtualMachineError就屬於錯誤.

按照Java慣例, 不應該實現任何新的Error子類, 需要自定義異常可以採用Exception類.

到底該哪一種異常?

對於可以恢復的條件使用被檢查異常,對於程序錯誤使用運行時異常.虛擬機及系統錯誤採用Error.

③ 捕獲異常

使用trycatch關鍵字可以捕獲異常.try/catch代碼塊放在異常可能發生的地方.

語法如下:

try {
    /** 程序代碼*/} catch (Exception e) {
    /** 異常處理*/}

一個try代碼塊後面跟隨多個catch代碼塊的情況就叫多重捕獲. 可以在 try 語句後面添加任意數量的 catch 塊. 如果保護代碼中發生異常,異常被拋給第一個 catch 塊. 如果拋出異常的數據類型與捕獲異常類型匹配, 就會被捕獲. 如果不匹配,它會被傳遞給下一個catch塊.直到異常被捕獲或者通過所有的catch塊.

語法如下:

try {
    /** 程序代碼*/} catch (Exception1 e) {
    /** 異常處理*/} catch (Exception1 e) {
    /** 異常處理*/}

④ 拋出異常

可以使用throw關鍵字拋出一個異常.

public static void testThrow() {
    /** 方法體*/
    throw new NullPointerException();}

如果一個方法沒有捕獲一個編譯異常, 那麼該方法必須使用throws關鍵字來聲明. throws關鍵字放在方法簽名的尾部.

示例代碼:

public static void testThrows() throws NullPointerException {
    /** 方法體*/}

一個方法可以聲明拋出多個異常,多個異常之間用逗號隔開.

例如,下面的方法聲明拋出NullPointerExceptionArithmeticException

示例代碼:

public static void testThrows() throws NullPointerException, ArithmeticException {
    /** 方法體*/}

⑤ finally關鍵字

finally關鍵字用來創建在try代碼塊後面執行的代碼塊. 無論是否發生異常,finally代碼塊中的代碼總會被執行. 在finally代碼塊中,可以運關閉鏈接, 釋放系統資源等必須要執行的語句.

finally代碼塊出現在catch代碼塊最後.

語法如下:

try {
    /** 方法體*/} catch (Exception e) {
    /** 異常處理*/} finally {
    /** finally語句*/}

finally 塊並非強制添加.

try 代碼後不能既沒 catch 塊也沒 finally 塊.

示例代碼:

package com.dashidan.lesson15;/**
 * 大屎蛋教程網-dashidan.com
 * <p>
 * Java教程基礎篇: 15.Java異常
 * 測試finally return
 */public class Demo2 {
    public static void main(String[] args) {
        int result = testFinallyReturn();
        System.out.println("result: " + result);
    }

    public static int testFinallyReturn() {
        int a;
        try {
            a = 1;
            /** 拋出異常*/
            System.out.println("拋出異常");
            throw new NullPointerException();
        } catch (NullPointerException e) {
            a = 2;
            /** 捕獲異常*/
            System.out.println("捕獲異常");
            e.printStackTrace();
            /** 注意這裏沒有返回*/
            System.out.println("注意這裏沒有返回");
            return a;
        } finally {
            a = 3;
            System.out.println("finally執行返回");
            /** 拋出異常後, 執行finally的語句, 如果這裏返回,不再執行catch中語句*/
            return a;
        }
    }}

輸出:

拋出異常
捕獲異常
注意這裏沒有返回
finally執行返回
result: 3
java.lang.NullPointerException
    at com.dashidan.lesson15.Demo2.testFinallyReturn(Demo2.java:21)
    at com.dashidan.lesson15.Demo2.main(Demo2.java:11)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

⑥ 自定義異常

Java中自定義異常需要注意:

  • 所有異常都必須是 Throwable 的子類.

  • 如果想寫一個檢查性異常類,則需要繼承 Exception 類.

  • 如果想寫一個運行時異常類,那麼需要繼承 RuntimeException 類.

package com.dashidan.lesson15;/**
 * 大屎蛋教程網-dashidan.com
 * <p>
 * Java教程基礎篇: 15.Java異常
 * 自定義異常
 */public class SelfException extends Exception {}

示例代碼:

package com.dashidan.lesson15;/**
 * 大屎蛋教程網-dashidan.com
 * <p>
 * Java教程基礎篇: 15.Java異常
 */public class Demo1 {
    public static void main(String[] args) {
        try {
            /** 方法體*/
            testThrow();
            testThrows();
        } catch (NullPointerException e) {
            /** 異常處理*/
            System.out.println("run catch NullPointerException.");
            e.printStackTrace();
        } catch (Exception e) {
            /** 異常處理*/
            System.out.println("run catch Exception.");
            e.printStackTrace();
        } finally {
            /** finally語句*/
            System.out.println("run finally.");
        }
    }

    public static void testThrow() {
        /** 方法體*/
        throw new NullPointerException();
    }

    public static void testThrows() throws NullPointerException, ArithmeticException {
        /** 方法體*/
    }}

輸出:

java.lang.NullPointerException
at com.dashidan.lesson15.Demo1.testThrow(Demo1.java:30)
at com.dashidan.lesson15.Demo1.main(Demo1.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
run catch NullPointerException.
run finally.

⑦ 相關文章

 Java從入門到精通目錄



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章