JavaSE 異常拋光解析

来源:https://www.cnblogs.com/ownmg/archive/2019/04/14/10707592.html
-Advertisement-
Play Games

異常 異常指的是程式中的不正常現象,一般異常都是由第三方數據的使用造成的。java中每種異常現象都會有一個對應的異常類。java對異常的處理方式就是終止程式。異常機制其實是為了幫助我們找到程式中的問題。異常指的並不是語法錯誤,語法錯了,編譯不通過,不會產生位元組碼文件,根本不能運行。 異常體系 jav ...


異常

異常指的是程式中的不正常現象,一般異常都是由第三方數據的使用造成的。java中每種異常現象都會有一個對應的異常類。java對異常的處理方式就是終止程式。異常機制其實是為了幫助我們找到程式中的問題。異常指的並不是語法錯誤,語法錯了,編譯不通過,不會產生位元組碼文件,根本不能運行。

異常體系

java將程式中遇到的每一種異常現象都封裝成一個對應的異常類。然後將眾多的異常抽取成一個異常體系。而整個異常系統又分為: 錯誤 和 異常兩種現象。

  • java.lang.Throwable:異常體系的頂層父類。其下有兩個子類:
    • java.lang.Error: 錯誤體系的頂層父類。嚴重的錯誤Error,無法處理,只能預先避免,好比絕症。
    • 比如開闢數組空間的個數過多,導致記憶體不夠使用。這不是代碼的問題,而是硬體不足造成的。
    • java.lang.Exception:異常體系中的頂層父類。程式中的異常就是指java.lang.Exception。
    • 程式中一旦產生了異常的現象,程式開發人員可以通過代碼糾正(就好比生活中身體出現異常,可以通過藥物或其他方式進行治療)。異常是必須要處理的(好比發燒、感冒、闌尾炎)。

小結

Throwable是異常體系的根類。針對於程式中的異常,分為:錯誤(Error)和異常(Exception)。

Error:無法處理,儘量避免。

Exception:必須處理。

異常的產生過程解析

當我們操作了數組不存在的下標時,程式會產生一個數組索引越界異常ArrayIndexOfBoundsException。我們通過圖解來解析下異常產生的過程。

步驟

  1. 創建一個數組的工具類,類中定義靜態方法getElement(),通過提供的數組和下標獲取對應的元素。
  2. 創建測試類,在類中定義數組,開闢空間個數3。
  3. 通過數組工具類名調用獲取數組元素的方法,並傳遞創建的數組和4下標。
  4. 運行程式,查看結果。

實現

工具類

public class ArrayTools {
    // 對給定的數組通過給定的角標獲取元素。
    public static int getElement( int[] arr, int index ) {
        int element = arr[index];
        return element;
    }
}

測試類

public class ExceptionDemo {
    public static void main(String[] args) {
        int[] arr = { 34, 12, 67 };
        int num = ArrayTools.getElement(arr, 4)
        System.out.println("num = " + num);
        System.out.println("over");
    }
}

上述程式執行過程圖解:

小結

當程式中的數據產生異常之後,JVM會識別當前異常。然後將異常的信息進行封裝,拋給程式的調用者,讓調用者基於獲取的異常信息進行處理。而如果沒有對異常進行處理,則異常最後會由JVM進行處理。JVM處理的方式就是終止程式,並將異常的信息列印到控制台。

異常分類和處理

目標

程式中需要開發人員處理的異常指的是Exception,這類異常一旦出現,我們就要對代碼進行更正,修複程式。

異常(Exception)的分類:分為 編譯時期異常 和 運行時期異常。

  • 編譯時期異常:在編譯時期,就會檢查。如果沒有處理異常,則編譯失敗。( 如日期格式化異常 )
    • Exception :編譯時期異常頂層父類。除特殊的子類外,其下所有子類都屬於編譯時期異常類。
  • 運行時期異常:在運行時期,檢查異常。運行中發現異常則程式停止運行。編譯時期,不會被編譯器檢測。
    • RuntimeException :Exception的一個特殊子類,運行時期異常頂層父類。其下的所有子類都屬於運行時期的異常類。如:下標越界。
  • 異常的處理
    • 編譯時期異常:編譯時就會編譯報錯,因此必需要處理。只有處理之後才能編譯成功,產生class文件。然後才能夠讓程式運行。
    • 運行時期異常:編譯時期不會檢查,運行時期檢測。如果運行時真的出現了異常現象JVM會結束程式。針對於運行時期異常:可以處理,也可以不用處理,一般不處理。

步驟

  1. 在演示異常的類中創建意思日期字元串。
  2. 創建DateFormat對象,並調用parse()方法解析日期字元串(編譯異常)
  3. 對比分析編譯時期和運行時期異常類。

實現

public class ExceptionDemo {
    public static void main(String[] args) {
        int[] arr = { 34, 12, 67 };
        /*
            運行時期的異常,只有在運行時才會檢測。編譯時期不會檢測。
         */
        int num = ArrayTools.getElement(arr, 4);
        System.out.println("num = " + num);

        // 創建日期字元串
        String time = "2018-12-12";
        // 創建DateFormat對象,解析日期字元串
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        /*
            調用parse()方法,解析日期字元串。
            當前方法上有一個編譯時期的異常,針對於編譯時期異常一定要進行處理。
            否則編譯會報錯。
          */
        Date parse = df.parse(time);
        System.out.println("parse = " + parse);

        System.out.println("over");
    }
}

小結

異常分為

編譯時期異常 : 頂層父類Exception,編譯時期檢測,必須要處理的異常。

運行時期異常 : 頂層父類RuntimeException,運行時期檢測,選擇性處理的異常。一般不處理。

異常的處理

Java異常處理的五個關鍵字:try、catch、finally、throw、throws

拋出異常throw

方法上經常要接收調用者傳遞的數據,而方法本身對於傳遞的數據通常會有範圍的限定,超出範圍即為不合法的數據。因此在程式開發時,通常需要對方法上傳遞的參數進行合法性的判斷。如果傳遞的數據不合法,我們則需要將數據非法(異常)的具體信息告知給方法的調用者。就好像生活中看醫生,如果身體出現了異常的現象,醫生會告訴我們具體的病情一樣的道理。

在java中如果需要將數據異常的信息告訴給方法的調用者知道,則需要使用throw關鍵字 。代碼體現就是將異常信息進行封裝,然後使用throw關鍵字拋出給調用者。

  • throw關鍵字:用來拋出一個異常對象,將這個異常對象傳遞給調用者,並結束當前方法的執行。步驟:
    1. 創建一個異常對象。封裝異常的一些提示信息( 信息可以自己編寫 )。
    2. 通過throw關鍵字,將這個封裝異常信息的對象告知給調用者。

使用格式:

throw new 異常類名(參數);

例如:

throw new NullPointerException("要訪問的arr數組不存在");

throw new ArrayIndexOutOfBoundsException("該索引在數組中不存在,已超出範圍");

註意:異常在拋出時可以分為兩種情況,即:拋出 編譯時期異常 或者 運行時期異常。並且拋出的異常對象必須是異常體系所屬的類。

學習完拋出異常的格式後,我們通過下麵程式演示下throw的使用。

步驟

  1. 定義getElement()方法,傳遞int數組和下標。
  2. 使用if判斷,傳遞的下標數據是否合法,如果不合法則拋出下標越界異常並提示異常信息。
  3. 實現功能,通過下標獲取數組中下標對應的元素。
  4. 調用方法,查看結果。

實現

public class ThrowDemo {
    public static void main(String[] args) {
        //創建一個數組 
        int[] arr = {2,4,52,2};
        //根據索引找對應的元素 
        int index = 4;
        int element = getElement(arr, index);

        System.out.println(element);
        System.out.println("over");
    }
    /*
     * 根據 索引找到數組中對應的元素
     */
    public static int getElement( int[] arr,int index ){ 
        //判斷  索引是否越界
        if( index < 0 || index > arr.length - 1 ) {
             /*
             判斷條件如果滿足,當執行完throw拋出異常對象後,方法已經無法繼續運算。
             這時就會結束當前方法的執行,並將異常告知給調用者。這時就需要通過異常來解決。 
              */
             throw new ArrayIndexOutOfBoundsException("哥們,下標越界了~~~");
        }
        int element = arr[index];
        return element;
    }
}

小結

程式中如果產生了問題,需要使用throw關鍵字,將描述問題的類即異常進行拋出,也就是將問題返回給該方法的調用者。 格式:

throw new 異常類("異常信息!");

使用throw關鍵字拋出的異常對象,必須是屬於異常體系的類對象。

註意:throw語句下麵,不能寫其他語句,否則會因為無法被執行而導致程式編譯報錯。

那麼對於調用者來說,該怎麼處理呢?基於運行時期異常,一般是不處理。而針對於編譯時期異常,一種是進行捕獲處理,另一種就是繼續將問題聲明出去,使用throws聲明處理。

Objects非空判斷

還記得我們學習過一個類Objects嗎,曾經提到過它由一些靜態的實用方法組成,這些方法是null-save(空指針安全的)或null-tolerant(容忍空指針的),那麼在它的源碼中,將對象為null的值,進行了拋出異常操作。

  • public static T requireNonNull(T obj):查看指定引用對象不是null。

查看源碼發現這裡對為null的進行了拋出異常操作:

public static <T> T requireNonNull( T obj ) {
    if ( obj == null )
        throw new NullPointerException();
    return obj;
}

步驟

  1. 定義getLength()方法,接收String類型數據,計算其長度並列印。
  2. 對傳遞的字元串數據進行合法性的判斷,判斷是否為空,如果為空則拋出空指針異常。
    • 先使用傳統的if判斷,然後使用Object類中的requireNonNull()方法進行操作。
  3. 對比兩種操作方式的區別。

實現

public static void getLength( String str ) {
    // if判斷傳遞的字元串數據是否合法(為null)
    /*if( str == null ) {
              throw new NullPointerException("字元串不能為null");
          }*/

    // Objects靜態方法requireNonNull()方法進行判斷
    Objects.requireNonNull( str ,"字元串不能為null");

    System.out.println(str + "長度為:" + str.length() );
}

小結

對傳遞的引用類型數據,一般都需要做控制針的判斷。Objects類中的requireNonNull()方法是專門用來判斷引用類型的參數是否為空的。

聲明異常 throws

throw關鍵字拋出的異常分為編譯時期異常 和 運行時期異常。針對於運行時期的異常可以不用作任何的操作處理。但如果拋出的是編譯時期的異常,則必須要進行處理。否則編譯報錯,程式無法運行。而對編譯時期異常的處理方式主要分為: 異常聲明 和 異常捕獲。

  • 聲明異常:將異常標識出來,報告給程式的使用者。讓程式的使用者在程式的編譯時期即可發現異常信息。
    • 例如生活中,超市售賣商品,有些商品快過期了,超市會在快過期的商品上貼上標簽。讓顧客在買商品時就能看到商品的異常信息。
  • throws關鍵字的作用就是在方法上進行異常的聲明,用於表示當前方法不處理異常,而是提醒該方法的調用者來處理異常( 繼續拋出異常 )。

聲明異常格式:

訪問許可權修飾符 返回值類型 方法名(參數) throws 異常類名1 , 異常類名2…{   }

註意:如果方法中拋出多個編譯時期異常,也可以只聲明多個異常的父類異常。

步驟

演示方法異常的聲明。

  1. 定義read( String path )方法。
  2. 對傳遞path變數進行判斷
    1. 判斷是否為null,為null則拋出空指針異常。(運行異常)
    2. 判斷path路徑地址是否為"a.txt",如果不是則拋出FileNotFoundException文件不存在異常(編譯異常)
    3. 判斷path路徑地址是否為"b.txt" , 如果不是則拋出IOException異常對象(編譯時期異常)
  3. 針對編譯時期異常進行聲明處理。
  4. 調用read()方法,並將main()方法被動接受到的異常繼續聲明到main()方法上。

實現

public class ThrowsDemo {
    public static void main(String[] args) throws FileNotFoundException, IOException {
        read("a.txt");
    }

    public static void read(String path) throws FileNotFoundException, IOException {
        if (!path.equals("a.txt")) {//如果不是 a.txt這個文件 
            // 我假設  如果不是 a.txt 認為 該文件不存在 是一個錯誤 也就是異常  throw
            throw new FileNotFoundException("文件不存在");
        }
        if (!path.equals("b.txt")) {
            throw new IOException();
        }
    }
}

小結

如果通過throw關鍵字拋出的編譯時期的異常,那麼就必須要對異常進行處理 , 聲明異常就是對編譯時期異常的一種處理方式:將程式的調用者在編譯時期就可以看到異常信息。需要使用throws關鍵字對異常進行聲明:

訪問許可權修飾符 返回值類型 方法名(參數) throws 異常類名1, 異常類名2...{}

註意:

  1. throws關鍵字只能用在方法的聲明處。
  2. throws聲明的類必須是異常體系中的類。
  3. 如果方法中拋出多個編譯時期異常,那麼也必須在方法上繼續聲明拋出多個異常,或多個異常的父類異常。
  4. 哪個方法調用了聲明異常的方法,那麼當前方法就會被動接受被調用方法上的異常。

捕獲異常try…catch

使用異常的聲明時,如果方法中真的出了現異常現象,那麼JVM就會將程式終止。造成的後果是後續的代碼無法繼續正常的執行。而如果希望即使出現了異常的現象,也能讓後續的代碼繼續執行,可以使用異常的另外一種處理方式:捕獲異常。

在java中使用:try-catch語句捕獲異常。

  • 捕獲異常:對異常語句,針對性進行捕獲,捕獲到異常信息後,可以對捕獲的異常進行自定義方式的處理。
    • 提示:JVM對異常的預設處理方式就是終止程式的運行。
  • 捕獲異常自定義處理的方式,Throwable中的常用方法:
    • public void printStackTrace(): 列印異常的詳細信息。
      包含了異常的類型,異常的原因,異常出現的位置,在開發和調試階段,都得使用printStackTrace。
    • public String getMessage() : 獲取發生異常的原因。提示給用戶的時候,就提示錯誤原因。

捕獲異常語法如下:

try{
     編寫可能會出現異常的代碼
} catch ( 異常類型 e ){
     處理異常的代碼
     //記錄日誌/列印異常信息/繼續拋出異常
}
/*
    try:該代碼塊中編寫可能產生異常的代碼。嘗試運行程式。
    catch:用來捕獲程式中產生的異常,並實現對捕獲到的異常進行處理。
    異常類型 e:用來接收throw關鍵字拋出的異常對象(也就是異常的信息,因為異常對象中封裝了異常的信息)
*/

註意:try 和 catch都不能單獨使用,必須連用。

步驟

演示使用try-catch語句捕獲異常。

  1. 定義read( String path )方法。
  2. 對傳遞path變數進行判斷
  3. 判斷path路徑地址是否為"a.txt",如果不是則拋出FileNotFoundException文件不存在異常(編譯異常)
  4. 針對編譯時期異常使用try-catch語句進行捕獲處理。
  5. 調用read()方法。

實現

public class TryCatchDemo {
    public static void main(String[] args) {
        // 調用方法  如果方法是聲明處理的異常,此處可以對方法進行捕獲處理。
        read("b.txt");
        System.out.println("over");
    }
    // 演示捕獲 異常
    public static void read(String path)  {
        //如果不是 a.txt這個文件
        if (!path.equals("a.txt")) {
            // 對異常進行捕獲處理
            try {
                throw new FileNotFoundException("文件不存在");
            }catch (FileNotFoundException e ) {
                // 自定義處理異常,輸出列印異常被捕獲
                System.out.println("異常被抓住了!!!");
            }
        }
        // 列印傳遞的參數
        System.out.println("path = " + path );
    }
}

小結

針對於程式中的編譯時期異常,除了聲明處理之外,也可以使用捕獲處理。

聲明處理:遇到異常JVM會終止程式的運行。

捕獲處理:遇到異常之後,可以自定義對異常處理。不用結束程式。

try{
  可能發生異常的代碼;
}catch( 異常類型 e ) {
  對捕獲的異常進行自定義的處理;
}
註意: try-catch 不能單獨使用。

提示:如果方法上的異常是聲明處理的,那麼調用異常方法的方法就會被動接收到異常。此時可以使用聲明的方式繼續將異常聲明出去,也可以使用try-catch語句進行捕獲。

finally 代碼塊

在使用try-catch代碼塊處理異常時,有可能發生異常的代碼是書寫在try代碼塊中。而在異常代碼的下麵,有時還會有其他代碼需要執行。但是一旦真有異常產生,程式會跳轉到catch代碼塊中執行代碼。那麼異常代碼後續的代碼是無法執行的。而如果異常語句下麵的代碼無論是否有異常產生都需要執行,則可以使用finally代碼塊完成。

finally代碼塊:在finally代碼塊中存放的代碼都是一定會被執行的。

當我們在try語句塊中打開了一些物理資源(磁碟文件/網路連接/資料庫連接等),我們都得在使用完之後,最終關閉打開的資源。

finally的語法:

try{
  有可能發生異常的代碼;
} catch( 異常類型 e ) {
  自定義處理異常;
} finally {
  無論是否有異常產生,都需要執行的代碼;
}

註意:finally不能單獨使用。

我們之後學習的IO流中,當打開了一個關聯文件的資源,最後程式不管結果如何,都需要把這個資源關閉掉。

步驟

演示finally代碼塊。

  1. 定義read( String path )方法。
  2. 對傳遞path變數進行判斷
  3. 判斷path路徑地址是否為"a.txt",如果不是則拋出FileNotFoundException文件不存在異常(編譯異常)
  4. 針對編譯時期異常使用throws進行聲明處理。
  5. 調用read()方法,並捕獲處理此方法。
  6. 在read()方法下麵,寫一個一定要執行的輸出語句。
  7. 傳遞異常數據,產生異常。查看輸出語句是否會被執行。
  8. 將一定要執行的輸出語句書寫到finally代碼塊中再次運行程式。查看結果。

實現

public class Demo {
    public static void main(String[] args) {
        try {
            readFile("b.txt");
            // 無論是否有異常產生都需要執行的代碼,寫在finally代碼塊中
            //System.out.println("無論是否有異常產生我都需要執行...");
        } catch ( FileNotFoundException e ) {
            // 表示異常被抓住並且已經處理了
            System.out.println("異常被抓住了..");
            // 結束當前JVM,此時finally語句不會執行 
            // System.exit(0); // 開發中一般不會使用
        } finally {
            // 無論是否有異常產生都需要執行的代碼,寫在finally代碼塊中
            System.out.println("無論是否有異常產生我都需要執行...");
        }
    }
    // 演示finally代碼塊的使用
    public static void readFile ( String file ) throws FileNotFoundException {
       if( !file.equals("a.txt") ) { // 如果不是a.txt文件
           // 假設如果不是a.txt文件,則認為該文件不存在,拋出對應的異常
           throw new FileNotFoundException("文件不存在!");
       }
    }
}

小結

finally代碼塊是用來書寫無論是否發生異常都需要執行的代碼語句。只有在try或者catch中調用退出JVM的相關方法,此時finally才不會執行,否則finally永遠會執行。

finally代碼塊註意事項

因為finally代碼塊中的代碼一定會被執行,所以一般不會將需要返回結果的代碼寫在finally代碼塊中。因為會永遠返回finally代碼塊中的結果。要儘量避免類似情況的發生。

步驟

  1. 定義getA()方法,返回int類型。
  2. 在方法內部定義變數 int a = 10;
  3. 定義try-catch-finally代碼塊
  4. 在try代碼塊中直接返回變數 a;
  5. 在finally代碼塊中給變數a重新賦值,返回在返回。
  6. 調用getA()方法。獲取返回的結果並查看。

實現

public class Demo {
    public static void main(String[] args) {
        // 調用方法,獲取返回值
        int i = gatA();
        System.out.println("i = " + i); // 100
    }
    // 演示捕獲 異常
    public static int gatA() {
        // 定義變數 a
        int a = 10;
        try{
            return a;
        }catch ( Exception e ) {
            System.out.println(e);
        } finally {
            a = 100;
            return a;
        }
    }
}

小結

如果finally代碼塊中有return語句,那麼一定會返回finally代碼塊中的結果。儘量避免類型情況的發生。

自定義異常

自定義異常類概述

在java中,一個異常類表示了一種異常現象。而這些異常類都JDK內部定義好的。但是實際開發中,也會出現很多異常現象,並且這些異常現象是JDK中沒有定義的。此時我們可以根據自己業務的異常情況來自定義異常類。

  • 自定義異常類 : 在開發中根據自己業務的異常情況自定義的異常類。
  • 自定義異常類註意事項 :
    • java中規定,只有Throwable異常體系的類,才能進行拋出或聲明等異常處理。
      • 所以自定義的異常類必須繼承異常類體系。
    • 自定義一個編譯期異常:自定義類 並繼承於java.lang.Exception。
    • 自定義一個運行時期的異常類:自定義類 並繼承於java.lang.RuntimeException。

自定義異常類格式

訪問許可權修飾符 class 異常類名 extends Exception | RuntimeException {
  // 空參構造
  public 異常類名(){}
  // 異常信息提示構造  使用字元串數據提示異常的具體信息
  public 異常類名( String message ){
    super( message );
  }
}

步驟

定義一個註冊異常的編譯時期異常類。

  1. 自定義LoginException類。
  2. 繼承Exception類。
  3. 在類中定義空參構造 和 異常信息提示構造。

實現

// 業務邏輯異常
public class LoginException extends Exception {
    /**
     * 空參構造
     */
    public LoginException() {
    }

    /**
     *
     * @param message 表示異常提示
     */
    public LoginException(String message) {
        super(message);
    }
}

小結

當程式中出現異常現象時,我們需要將異常信息封裝,然後拋出給程式的調用者知道。代碼體現就是創建異常現象對應的異常類對象,然後使用throw關鍵字拋出。而如果程式中的異常現象沒有對應的異常類時,我們可以根據項目情況自己定義異常類。而java中規定,只有屬於異常體系的類才能使用處理異常的關鍵字進行處理。所以自定義的異常類要繼承異常體系類。

如果希望是編譯時期異常則繼承:Exception類。

如果希望是運行時期異常則繼承:RuntimeException類。

自定義的異常類中需要提供一個空參構造,一個異常信息提示的構造方法。

自定義異常的練習

步驟

要求:我們模擬登陸操作,如果用戶名已存在,則拋出異常並提示:親,該用戶名已經被註冊。

  1. 定義一個靜態的成員字元串數組,併在數組中聲明幾個賬號,用於模擬資料庫。
  2. 定義checkUsername( String name )方法,判斷註冊的賬號是否存在
  3. 遍歷取出模擬資料庫數組中的數據
  4. 使用資料庫中已經存在的賬號和註冊的賬號進行比較。如果用戶名已存在,則拋出異常並提示:親,該用戶名已經被註冊。

實現

public class Demo {
    // 模擬資料庫已經存在的賬號
    private static String[] names = {"zhangSan","liSi","wangWu"};

    public static void main(String[] args) {
        // 調用方法
        try{
            // 可能出現異常的代碼
            checkUsername("liSi");
            // 沒有發生異常,則表示註冊成功
            System.out.println("賬號註冊成功!!");
        }catch ( LoginException e ) {
            // 處理異常
            e.printStackTrace();
        }
    }

    // 判斷當前賬號是否存在
    public static boolean checkUsername ( String unams ) throws LoginException {
        // 迴圈資料庫中的所有賬號
        for( String name : names ) {
            // 將取出的資料庫中的賬號和申請的賬號比價
            if( unams.equals( name ) ) {
                // 如果進入if說明賬號已經存在,則拋出賬號存在異常
                throw new LoginException("賬號已經存在!!");
            }
        }
        // 沒有拋出異常,說明賬號不存在。
        return true;
    }
}

小結

自定義異常類和JDK中定義好的異常類的使用方式都是一樣的。也可以通過throw關鍵字拋出,通過throws關鍵字聲明,或者通過try-catch代碼塊進行捕獲處理。

3.3 多個異常捕獲擴展

在程式中,異常現象不可能只出現一個。有時一個程式中會出現多個異常現象。多個異常的捕獲,有多種不同的方式。

多個異常多次捕獲多次處理

步驟

  1. 自定義異常A類,繼承Exception類。
  2. 自定義異常B類,繼承繼承A類。
  3. 定義getAException( int a )方法,並對a進行判斷,如果a==0,則拋出A異常。
  4. 定義getBException( int b )方法,並對b進行判斷,如果b==0,則拋出B異常。
  5. 調用getAException( int a ),並使用捕獲處理。
  6. 調用getBException( int b ),並使用捕獲處理。

實現

// 自定義異常A類
public class A extends RuntimeException {
    // 空參構造
    public A() { }

    // 異常提示構造
    public A(String message) {
        super(message);
    }
}

// 自定義異常B類,繼承A類
public class B extends A {
    // 空參構造
    public B() {}

    // 異常提示構造
    public B(String message) {
        super(message);
    }
}

// 演示多個異常的單獨處理
public class Demo {
    public static void main(String[] args) {
        // 單獨處理A異常
        try{
            getAException(0);
        }catch ( A e ) {
            System.out.println("異常被抓住了...");
            e.printStackTrace();
        }

        // 單路處理B異常
        try {
            getBException(0);
        } catch ( B e ) {
            System.out.println("異常被抓住了...");
            e.printStackTrace();
        }

        /*
            針對於運行時期異常,使用try-catch的方式進行捕獲。
            好處在於: 即使有異常發生,後續代碼也可以繼續執行。
        */
        System.out.println("後續代碼....");
    }

    // 定義方法,拋出A類異常
    public static void getAException( int a ) {
        if( a == 0 ) {
            throw new A("不能為0!");
        }
    }
    // 定義方法,拋出B類異常
    public static void getBException( int b ) {
        if( b == 0 ) {
            throw new B("不能為0!");
        }
    }
}

小結

當程式中有多個異常時,基於需求的需要我們可以對多個異常分別使用try-catch語句進行捕獲處理。

多個異常一次捕獲多次處理

try-catch代碼塊擴展語法:

try{
     編寫可能會出現異常的代碼
}catch( 異常類型A  e ){  //當try中出現A類型異常,就用該catch來捕獲.
     處理異常的代碼
     //記錄日誌/列印異常信息/繼續拋出異常
}catch( 異常類型B  e ){  //當try中出現B類型異常,就用該catch來捕獲.
     處理異常的代碼
     //記錄日誌/列印異常信息/繼續拋出異常
}

步驟

  1. 調用getAException( int a )
  2. 調用getBException( int b )
  3. 對兩個異常方法一次進行捕獲
  4. 使用多個catch代碼塊處理捕獲的多個異常

實現

// 演示多個異常的一次捕獲,多次處理
public class Demo {
    public static void main(String[] args) {
        // 多個異常一次捕獲,多次處理
        try{
            getAException(0);
            getBException(0);
        }catch ( B e ) {
            System.out.println("B類異常被抓住了...");
            e.printStackTrace();
        }catch ( A e ) {
            System.out.println("A類異常被抓住了...");
            e.printStackTrace();
        }
    }
    // 定義方法,拋出A類異常
    public static void getAException( int a ) {
        if( a == 0 ) {
            throw new A("不能為0!");
        }
    }
    // 定義方法,拋出B類異常
    public static void getBException( int b ) {
        if( b == 0 ) {
            throw new B("不能為0!");
        }
    }
}

小結

當程式中有多個異常時,基於需求的需要我們可以對多個異常使用try代碼塊一次捕獲,然後使用多個catch語句分別對異常進行處理。

註意:這種異常處理方式,要求多個catch中的異常不能相同,並且若catch中的多個異常之間有子父類異常的關係,那麼子類異常要求在上面的catch處理,父類異常在下麵的catch處理。

多個異常一次捕獲一次處理

步驟

  1. 調用getAException( int a )
  2. 調用getBException( int b )
  3. 對兩個異常方法一次進行捕獲
  4. 使用一個catch代碼塊處理捕獲的多個異常

實現

// 演示多個異常的一次捕獲,一次處理
public class Demo {
    public static void main(String[] args) {
        // 多個異常一次捕獲,一次處理
        try{
            getAException(1);
            getBException(0);
        }catch ( A e ) {
            System.out.println("類異常被抓住了...");
            e.printStackTrace();
        }
    }
    // 定義方法,拋出A類異常
    public static void getAException( int a ) {
        if( a == 0 ) {
            throw new A("a不能為0!");
        }
    }
    // 定義方法,拋出B類異常
    public static void getBException( int b ) {
        if( b == 0 ) {
            throw new B("b不能為0!");
        }
    }
}

小結

當程式中有多個異常時,基於需求的需要我們可以對多個異常使用try代碼塊一次捕獲,然後使用一個catch語句對異常進行處理。

註意:這種異常處理方式,要不catch語句中的異常類型,必須是多個異常的父類類型。能夠接收任意一個被拋出的異常對象。

繼承中異常註意事項

  • 如果父類聲明瞭多個異常,子類重寫父類方法時,只能聲明相同的異常或者是他的子集。也可以不聲明
  • 父類方法沒有聲明異常,子類重寫父類該方法時也不可拋出異常。此時子類產生該異常,只能捕獲處理,不能聲明拋出

步驟

  1. 創建父類,在類中定義show( int a , int b )方法.
  2. 分別對變數 a 和 b進行判斷,如果結果為0,則分別拋出A,B異常。
  3. 定義子類,重寫父類中的方法。驗證繼承中的異常註意事項。

實現

// 父類
class Fu {
    // 父類中的方法
    public void show( int a, int b ) throws A, B {
        if( a == 0 ) {
            throw new A("a不能為0!");
        }
        if( b == 0 ) {
            throw new B("b不能為0!");
        }
    }
}
class Zi extends Fu {
    // 子類重寫父類中的方法
    public void show( int a , int b ) throws B {
        System.out.println("重寫....");
    }
}

小結

繼承中,子類重寫父類方法時,父類沒有聲明異常。子類也不能聲明異常。如果父類上有聲明異常,子類重寫時可以不用聲明,或者聲明父類異常上的子類異常,但是異常的個數不能超過父類聲明的異常個數。

健康的父親,兒子也應該健康。多病的父親,基於進化學,兒子應該比父親健康。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我們今天繼續學習一下Numpy庫 接著前面幾次講的,Numpy中還有一些標準運算 exp表示求e的冪次方,比如上面看到的,e的0次方為1,e的2次方,2.7幾,以此類推 我們可以看到,exp就是求e的多少次方 而sqrt則表示根號,也就是進行開方運算 我們可以得到,0的開方為0,1 的開方為1,2的 ...
  • 靜態語言(C/C++、Java);腳本語言(python、JavaScript、PHP) IPO(Input、Process、Output) #:python中的註釋符號;‘’‘ ’‘’:多行註釋 python的35個保留字 數據類型:字元串、整數、浮點數、列表 整數類型:10011101 字元串類 ...
  • 上次使用了BeautifulSoup庫爬取電影排行榜,爬取相對來說有點麻煩,爬取的速度也較慢。本次使用的lxml庫,我個人是最喜歡的,爬取的語法很簡單,爬取速度也快。 本次爬取的豆瓣書籍排行榜的首頁地址是: https://www.douban.com/doulist/1264675/?start= ...
  • 新聞 "Hedgehog新站點" "Bolero 0.4發佈,增加遠程認證" "FsToolkit.ErrorHandling與Cvdm.ErrorHandling合併了" "F 里的3D圖形編程與游戲開發" "有趣的3D——瀏覽器里F 3D繪製" "F CNTK:變分自動編碼器例子——從2D隱空間 ...
  • 閱讀目錄 一、迭代器 1、迭代的概念 #迭代器即迭代的工具,那什麼是迭代呢? #迭代是一個重覆的過程,每次重覆即一次迭代,並且每次迭代的結果都是下一次迭代的初始值 代碼如下: 2、為何要用迭代器?什麼是可迭代對象?什麼是迭代器對象? 3、迭代器對象的使用 4、for迴圈 5、迭代器的優缺點 ...
  • 8、Bulk API 可以把多個 或`delete bulk API`中執行。這樣可以極大地提高索引速度。 API使用如下的JSON結構: 註意,最後一行數據必須要以 結尾。發送請求時,Content Type 標頭應設置為 application /x ndjson。 可以是 ,`create d ...
  • 一、引言 有了自動配置,springboot使web開發變得簡單,這個在springboot之旅中的第一篇中就有體現,實際的開發中當然不會這麼簡單,很多時候我們都需要自己去定製一些東西。web開發的東西比較多, 我們先掌握一些必要知識點,剩下的就是CRUD開發。 快速的創建一個springboot ...
  • 軟工作業2 ——實現一個能夠對文本文件中的單詞的詞頻進行統計的控制台程式 1.Github地址: https://github.com/wangshiyaoyao/WordCont 2.PSP表格 PSP2.1 Personal Software Process Stages 預估耗時(分鐘) 實際 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...