Java--異常的學習

可樂小巧粒發表於2020-11-22

throw關鍵字

package 異常學習;
/*
* java.lang.Throwable:類是java語言中所有錯誤或異常的超類
*       Excepttion:編譯期異常,進行編譯Java程式錯誤
*           RuntimeException:執行期異常,java程式在執行過程中出現的異常
*       Error:錯誤
*           錯誤必須通過修改原始碼,程式才能繼續執行
*
* 異常產生過程解析(分析異常怎麼產生的們如何處理異常)
*        方法將異常拋給main方法,main方法將異常拋給JVM
*
* 異常的處理:
*       1.丟擲異常throw關鍵字,可以在指定的方法中丟擲指定的異常
*               使用格式:
*                       throw new ***Exception("異常產生的原因");
*               注意事項:
*                   1.throw關鍵字必須寫在方法的內部
*                   2.throw關鍵字後邊new物件必須是Exception或者是Exception的子類物件
*                   3.throw關鍵字丟擲指定的異常物件。我們就必須處理這個異常物件
*                           throw關鍵字後邊建立的是RuntimeException或者是RuntimeException的子類物件,我們可以不處理,預設交給JVM處理(列印異常,中斷程式)
*                           throw關鍵字後邊建立的是編譯異常(寫程式碼的時候報錯),我們就必須處理這個異常,要麼throws,要麼try...catch...
*
* */
public class Demo01Exception {
    public static void main(String[] args) {
        //建立陣列 並賦值
        int[] arr = {1, 2, 3, 4};
//        int[] arr = null;
        int e = getElements(arr, 6);//Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 4
//        System.out.println(e);


    }

    /*
    * 建立一個方法,獲取陣列指定索引的元素
    * 以後工作中,我們首先對方法傳遞過來的引數進行合法性校驗,
    * 如果引數不合法,納悶我們就必須使用丟擲異常的方式 告知方法的呼叫者,傳遞的引數有問題
    *   注意:
    *       異常.NullPointerException: 傳遞的陣列值是空是一個執行期異常,我們不用處理,預設交給JVM處理
    * */
    public static int getElements(int[] arr,int index) {
        /*
        * 我們對傳遞過來的引數進行合法性校驗
        * 如果陣列arr的值是null,那麼我們就丟擲空指標異常,告知呼叫者傳遞的陣列值是空
        * */
        if (arr == null) {
            throw new NullPointerException("傳遞的陣列值是空");
        }
        /*
        * 我們可以對傳遞過來的index進行合法性校驗,如果index不在陣列索引範圍內
        * 就丟擲陣列索引越界異常
        * */
        if (index < 0 || index > arr.length - 1) {
            throw new ArrayIndexOutOfBoundsException("陣列的索引越界了");
        }
        int ele = arr[index];
        return ele;
    }
}
########################執行結果#################
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 陣列的索引越界了
	at 異常學習.Demo01Exception.getElements(Demo01Exception.java:55)
	at 異常學習.Demo01Exception.main(Demo01Exception.java:29)

Objects非空判斷

package 異常學習;

import java.util.Objects;

/*
* Objects類中的靜態方法:
*   public static <T> T requireNonNull(T obj) :檢視指定引用物件不是null
* 原始碼:
* public static <T> T requireNonNull(T obj) {
*   if (obj == null)
*       throw new NullPointerException();
*   return obj;
* }
*
* */
public class Demo02Objects {
    public static void main(String[] args) {
        method(null);
    }

    //建立一個方法
    public static void method(Object obj) {
//        //對傳遞的引數進行合法性判斷,判斷是否為空
//        if (obj == null) {
//            throw new NullPointerException("傳遞的物件值是空");
//        }
        //等價於直接呼叫Objects的非空判斷
//        Objects.requireNonNull(obj);
        Objects.requireNonNull(obj, "傳遞的物件值是空");
    }
}
#####################執行結果#############
Exception in thread "main" java.lang.NullPointerException: 傳遞的物件值是空
	at java.base/java.util.Objects.requireNonNull(Objects.java:233)
	at 異常學習.Demo02Objects.method(Demo02Objects.java:29)
	at 異常學習.Demo02Objects.main(Demo02Objects.java:18)

throws處理異常的第一種方式

package 異常學習;

import java.io.FileNotFoundException;
import java.io.IOException;

/*
* throws關鍵字:異常處理的第一種方式,交給別人處理
* 作用:
*       當方法內部丟擲異常物件的時候,那麼我們就必須處理這個異常物件
*       可以使用throws關鍵字處理異常物件,會把異常物件宣告拋給呼叫者使用(自己不處理,交給別人處理),最終交給JVM處理,中斷處理
* 使用格式:
*       修飾符 返回值型別 方法名(引數列表) throws AAAAException,BBBBException...{
*                       throw new AAAAException("產生的原因"));
*                       throw new BBBBException("產生的原因"));
*                   ....
*                   }
* 注意:
*       1.throws關鍵字必須寫在方法宣告處
*       2.throws關鍵字後邊宣告的異常必須是Exception或者是Exception的子類
*       3.方法內部如果丟擲了多個異常,那麼throws關鍵字後邊也必須宣告多個異常
*           如果丟擲的異常 有子父類關係,那麼直接宣告父類異常即可
*       4.呼叫了一個宣告丟擲異常的方法,我們就必須處理宣告的異常
*           要麼繼續使用throws丟擲異常,要麼try...catch
* */
public class Demo03Throws {
    public static void main(String[] args) throws IOException {     //呼叫readFile方法時,也需要繼續丟擲異常 ,FileNotFoundException是IOException的子類,直接宣告父類異常就可以
        readFile("c:\\a.txt");

    }

    //定義一個方法,對傳播的檔案路徑進行合法性判斷
    //注意:FileNotFoundException是編譯異常,必須處理這個異常
    //可以使用throws繼續宣告丟擲這個異常物件,讓方法呼叫者處理
    public static void readFile(String filename) throws IOException {
        if (!filename.equals("c:\\b.txt")) {
            throw new FileNotFoundException("傳遞的路徑不是c:\\a.txt");
        }
        /*
        * 如果傳遞的路徑不是.txt結尾
        * 丟擲字尾名不對的異常
        * */
        if (!filename.endsWith(".txt")) {
            throw new IOException("檔名字尾不對");
        }
        System.out.println("路徑沒有問題,讀取檔案");
    }

}
################執行結果#####################
Exception in thread "main" java.io.FileNotFoundException: 傳遞的路徑不是c:\a.txt
	at 異常學習.Demo03Throws.readFile(Demo03Throws.java:36)
	at 異常學習.Demo03Throws.main(Demo03Throws.java:27)

try_catch 處理異常的第二種方式

Throwable類中3個異常處理的方式

package 異常學習;

import java.io.FileNotFoundException;
import java.io.IOException;

/*
* 異常處理的第二種方式:(自己處理)
*   格式:
*       try{
*           可能產生異常的程式碼
*       }catch(定義一個異常的變數,用來接收try丟擲的異常物件){
*           異常的處理邏輯,一般在工作中,會把異常資訊記錄到一個日誌中
*       }
*       ....
*       catch(異常型別 變數名){
*       }
*
* 注意:
*       1.try中可能出現多個異常物件,那麼就可以使用多個catch來處理這些異常
*       2.如果try產生異常。那麼就執行catch中的異常處理邏輯,執行完畢catch中的邏輯,繼續執行try...catch之後的程式碼
*          如果try沒有產生異常,就不會處理catch中的處理邏輯,直接執行try...catch之後的程式碼
*
* */
public class Demo04TryCatch {
   public static void main(String[] args) {
       try {
           readFile("d:\\a.tx");
           System.out.println("這裡需要使用finally程式碼塊,才能夠在有異常的時候讀到");

       } catch (IOException e) {      //try丟擲什麼異常物件,catch就定義什麼異常物件,用來接收這個異常物件
//            System.out.println("catch--傳遞的檔案地址字尾不對");

           /*
           * Throwable類中定義了3個異常處理的方法:
           *   	String getMessage()      返回此 throwable 的簡短描述
           *        String	toString()       返回此 throwable 的詳細描述
           *      void	printStackTrace()    將此 throwable 及其追蹤輸出至標準錯誤流
            * */

//            System.out.println(e.getMessage());
           /*執行結果:檔名字尾不對
           * */
//            System.out.println(e.toString());
           /*執行結果:java.io.IOException: 檔名字尾不對
           * */
           e.printStackTrace();
           /*執行結果:java.io.IOException: 檔名字尾不對
           * at 異常學習.Demo04TryCatch.readFile(Demo04TryCatch.java:58)
           * at 異常學習.Demo04TryCatch.main(Demo04TryCatch.java:27)
           * */

       }
       System.out.println("後續程式碼");

   }
   public static void readFile(String filename) throws IOException {

       /*
        * 如果傳遞的路徑不是.txt結尾
        * 丟擲字尾名不對的異常
        * */
       if (!filename.endsWith(".txt")) {
           throw new IOException("檔名字尾不對");
       }
       System.out.println("路徑沒有問題,讀取檔案");
   }
}
##########################執行結果################
java.io.IOException: 檔名字尾不對
   at 異常學習.Demo04TryCatch.readFile(Demo04TryCatch.java:63)
   at 異常學習.Demo04TryCatch.main(Demo04TryCatch.java:27)
後續程式碼

finally程式碼塊

package 異常學習;

import java.io.FileNotFoundException;
import java.io.IOException;

/*
* finally:有一些特定的程式碼無論異常是否發生,都需要執行。
* 另外,因為異常會引發程式跳轉,導致有些語句執行不到。
* 而finally就是解決這個問題的,在finally程式碼塊中存放的程式碼都是一定會被執行的。
*    如果finally有return語句,永遠返回finally中的結果,應該避免該情況.
*
* 格式:
*        try{
*           可能產生異常的程式碼
*       }catch(定義一個異常的變數,用來接收try丟擲的異常物件){
*           異常的處理邏輯,一般在工作中,會把異常資訊記錄到一個日誌中
*       }
*       ....
*       catch(異常型別 變數名){
*       }finally{
*           無論是否出現異常都會執行
*       }
*
* 注意:
*   1.finally不餓能單獨使用,必須和try一起使用
*   2.finally一般用於資源釋放(資源回收),無論程式是否出現異常,最後都要資源釋放(IO)
*
* */
public class Demo05finally {
    public static void main(String[] args) {
        try {

            readFile("d:\\a.tx");
        } catch (IOException e) {

            e.printStackTrace();
        }finally {
            //無論是否出現異常都會執行
            System.out.println("資源釋放");
        }
    }


    public static void readFile(String filename) throws IOException {

        /*
         * 如果傳遞的路徑不是.txt結尾
         * 丟擲字尾名不對的異常
         * */
        if (!filename.endsWith(".txt")) {
            throw new IOException("檔名字尾不對");
        }
        System.out.println("路徑沒有問題,讀取檔案");
    }

}
#####################執行結果################
java.io.IOException: 檔名字尾不對
	at 異常學習.Demo05finally.readFile(Demo05finally.java:51)
	at 異常學習.Demo05finally.main(Demo05finally.java:33)
資源釋放

多異常處理

package 異常學習;

import java.util.List;

/*
* 多個異常使用捕獲又該如何處理呢?
*   1. 多個異常分別處理。
*   2. 多個異常一次捕獲,多次處理。
*   3. 多個異常一次捕獲一次處理。
*
*       此外:父類是什麼異常,子類就是什麼異常
* */
public class Demon06多異常處理 {

    public static void main(String[] args) {
        //1. 多個異常分別處理。
        /*try {
            int[] arr = {1, 2, 3};
            System.out.println(arr[3]);
        } catch (ArrayIndexOutOfBoundsException a) {
            a.printStackTrace();
        }

        try {
            List<Integer> list = List.of(1, 2, 3);
            System.out.println(list.get(3));
        } catch (IndexOutOfBoundsException e) {
            e.printStackTrace();
        }
        System.out.println("後續程式碼");
        */

        //2.多個異常一次捕獲,多次處理。
        /*try {
            int[] arr = {1, 2, 3};
            System.out.println(arr[4]);
            List<Integer> list = List.of(1, 2, 3);
            System.out.println(list.get(6));

        } catch (ArrayIndexOutOfBoundsException a) {
            a.printStackTrace();
        } catch (IndexOutOfBoundsException e) {      //catch中定義的異常物件,如果有子父類關係,那麼子類的異常變數必須寫在上面,否則就會報錯
            e.printStackTrace();
        }
        */
        //3. 多個異常一次捕獲一次處理。
        try {
            int[] arr = {1, 2, 3};

            List<Integer> list = List.of(1, 2, 3);
            System.out.println(list.get(6));
            System.out.println(arr[4]);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
#################執行結果###############
java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 3
	at java.base/java.util.ImmutableCollections$ListN.get(ImmutableCollections.java:547)
	at 異常學習.Demon06多異常處理.main(Demon06多異常處理.java:51)

自定義異常

package 異常學習;

/*
 * 自定義異常類:
 *       格式:
 *           public class XXXException extends Exception | RunTimeException{
 *               新增一個空引數的構造方法;
 *               新增一個帶異常資訊的構造方法;
 *           }
 *       注意:
 *           1.自定義異常類一般都是以Exception結尾,說明該類是一個異常類
 *           2.必須繼承Exception(編譯異常,必須處理,要麼throws要麼try..catch) | RunTimeException(執行異常)(無需處理,交給JVM處理)
 * */
public class Demo07自定義異常 extends Exception {
    public Demo07自定義異常() {
        super();
    }
    /*
    * 新增一個帶異常資訊的構造方法
    * 檢視原始碼都會發現,所有的異常類都會有一個帶異常資訊的構造方法,方法內部會呼叫父類帶異常資訊的構造方法,讓父類來處理這個異常資訊
    * */

    public Demo07自定義異常(String message) {
        super(message);
    }
}

相關文章