天天看點

【小白學Java】D27》》》程式的異常處理 try - catch & throw & throws& 自定義異常一、什麼是異常?二、異常的體系及分類三、異常的産生過程分析四、異常的處理五、自定義的異常類制作不易,各位友友們,大佬們給點鼓勵!

一、什麼是異常?

        異常就是不正常的意思。就像生活中,正在路上行使的汽車,遇到了故障,發動機突然抛錨停止了運轉,導緻汽車不能正常的行駛。這樣的情況,在程式開發過程中就叫做”異常“。異常就是指在程式的執行過程中出現的非正常的情況,而這種非正常的情況最終會導緻JVM(java虛拟機)非正常的停止。 主要表現為在內建開發環境中,代碼上會出現紅色的下劃線亦或者是紅色的波浪線,在控制台(console)上程式會運作中斷并會抛出一個異常資訊。

        像在Java等面向對象的程式設計語言中,異常本身其實就是一個類(異常類),而産生異常其實就是建立了一個異常對象,并且抛出了該異常對象。Java中對異常的處理方式是中斷處理。

        有一個很關鍵的點,朋友們要注意了,特别是初學者最容易搞混了。我們要注意,導緻出現異常的錯誤原因,并不包括文法錯誤。 我們通常寫的源代碼就是”.java“字尾的檔案,都需要經過java編譯器也就是JVM編譯過後産生的一個”.class“字尾的檔案,最終才能運作出來。而這裡,如果是文法出現錯了,那麼就會導緻代碼的編譯不通過,就不會産生位元組碼檔案,那麼程式就根本運作不了,前面說的異常就是抛出一個異常類的異常對象,而現在程式無法運作就不會産生并抛出異常類的對象,是以說,異常并不包括文法錯誤。

【小白學Java】D27》》》程式的異常處理 try - catch & throw & throws& 自定義異常一、什麼是異常?二、異常的體系及分類三、異常的産生過程分析四、異常的處理五、自定義的異常類制作不易,各位友友們,大佬們給點鼓勵!

那麼,今天呢,小北有幸能和大家分享,小北在學習異常處理時所避的坑。

小北在學習時,已經整理好了自己的學習筆記,Java中的異常處理相關的知識以及初學者需要注意,需要重點掌握的知識點。今天分享給大家。

希望各位,走過的路過的友友們,大佬們,給小北點兒鼓勵,制作不容易

點贊👍 👍 👍 收藏+關注,一鍵三連走起!

二、異常的體系及分類

        異常機制就是用來幫助我們找到程式中出現的問題。Java中異常有一個根類,是java.lang.Throwable類,所有的異常都是由它繼承而來的。java.lang包下的Error類和java.lang.Exception類,分别是其兩個重要的子類,我們平時經常說的異常其實就是指的Exception。

java.lang.Error 就是指的很嚴重的錯誤,也就是無法處理的錯誤,而這種錯誤我們隻能事先避免,否則一旦出現,我們就必須修改源代碼。

java.lang.Exception: 表示異常,可以處理的錯誤,異常可以通過代碼的方式來處理(無需修改源代碼),使得程式能夠繼續運作,而異常是必須要處理的。 異常類有兩種異常;(1)程式運作期間的異常,也就是說在代碼運作期間會檢查有無異常産生,但是編譯時,編譯器不會進行檢查。(2)程式編譯期間的異常,在程式編譯期間進行檢查,如果沒處理異常,那麼就會導緻編譯失敗。

【小白學Java】D27》》》程式的異常處理 try - catch & throw & throws& 自定義異常一、什麼是異常?二、異常的體系及分類三、異常的産生過程分析四、異常的處理五、自定義的異常類制作不易,各位友友們,大佬們給點鼓勵!

三、異常的産生過程分析

看個例子:

public static void main(String[] args) {
      int[] array={1,2,3,4 };
      int a= printelement(array,4);
        System.out.println(a);
    }
    
    public static int printelement(int[] array,int i){
        int a= array[i];
        return a;
    }

           

(Ctrl+Shift+F10) 執行報錯:

【小白學Java】D27》》》程式的異常處理 try - catch & throw & throws& 自定義異常一、什麼是異常?二、異常的體系及分類三、異常的産生過程分析四、異常的處理五、自定義的異常類制作不易,各位友友們,大佬們給點鼓勵!

我們來分析一下異常的産生過程:

第一步:main方法中

int a= printelement(arr,4);

調用了

printelement(int[] arr,int i)

方法,來通路數組中的下标

index=4

的元素,但是數組下标是從0開始的沒有4索引,那麼這時JVM(java虛拟機)就會檢測到程式出現異常,JVM處理步驟是這樣的:

1.JVM會根據目前出現的,異常的産生原因,建立一個異常對象,并且該對象包含了産生異常的内容、原因和位置;

例如

new ArrayIndexOutOfBoundsException: 4

2.因為方法

printelement(int[] arr,int i)

中沒有寫處理異常的代碼邏輯(抛出異常 / try-catch),是以JVM就會把該異常對象,抛出給調用該方法的調用者(這裡是main方法)處理這個異常。

第二步:方法的調用者(main方法)接收到這個異常,若有處理異常的代碼邏輯,就會處理,若沒有,則繼續向調用者的上級調用者抛出這個異常,直到 ” 有人“ 來處理這個異常。

第三步:main方法的調用者是JVM,那麼JVM就會接收到這個異常對象并處理,處理邏輯是這樣的:

1.将異常對象的資訊(内容、原因、位置)以紅色的字型列印到控制台(console)

2.JVM會中止目前正在執行的java程式,也就是程式的中斷處理。

四、異常的處理

1、關鍵字throw

        throw關鍵字,用來在指定的方法中抛出一個指定的異常對象

(1)使用格式:
  throw new  ...Exception("産生異常的原因“);
  
(2)注意:
1.throw寫在方法的内部
2.throw new 對象必須是Exception類對象或者是其子類的對象
3.throw 批出的異常對象,必須處理
    3.1、throw new的是RuntimeException類對象或者是其子類的對象
             那麼就可以不處理,因為預設會交給JVM來處理
                            (jvm列印出異常對象的資訊并且中斷程式)
      3.2、throw new的是編譯異常,
             那麼就必須處理這個異常,throws或者try -catch

           
public static void main(String[] args) {
      int[] array1={1,2,3,4 };
      int a= printelement(array1,4);
      System.out.println(a);

      int[] array2=null;
      int b= printelement(array2,2);
      System.out.println(b);

  }

public static int printelement(int[] array,int i){
      //1.使用throw抛出異常
      
      //1.1 空指針異常 NullPointerException
      if(array ==null){
          throw new NullPointerException("數組為空");
      }
      
      //1.2 數組下标越界異常ArrayIndexOutOfBoundsException
      if(i<0 || i>= array.length){
          throw new ArrayIndexOutOfBoundsException("找不到索引,下标越界了");
      }

      int a= array[i];
      return a;
  }

           
【小白學Java】D27》》》程式的異常處理 try - catch &amp; throw &amp; throws&amp; 自定義異常一、什麼是異常?二、異常的體系及分類三、異常的産生過程分析四、異常的處理五、自定義的異常類制作不易,各位友友們,大佬們給點鼓勵!
【小白學Java】D27》》》程式的異常處理 try - catch &amp; throw &amp; throws&amp; 自定義異常一、什麼是異常?二、異常的體系及分類三、異常的産生過程分析四、異常的處理五、自定義的異常類制作不易,各位友友們,大佬們給點鼓勵!

注意:上面兩種異常都屬于運作時異常,都預設交給了JVM來處理

2、Object類中提供的一個判空方法

public static <T> T requireNonNull(T obj);
//檢視指定引用對象不是null,對傳遞過來的參數對象判斷是不是為空

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

           

有兩種重載的方法如圖: message------->資訊

【小白學Java】D27》》》程式的異常處理 try - catch &amp; throw &amp; throws&amp; 自定義異常一、什麼是異常?二、異常的體系及分類三、異常的産生過程分析四、異常的處理五、自定義的異常類制作不易,各位友友們,大佬們給點鼓勵!

3、聲明異常的關鍵字throws

        聲明異常就是指将問題标記出來并且報告給方法調用者。 如果方法内通過throw抛出了編譯時異常,但是并沒有捕獲處理該異常,那麼必須要使用throws關鍵字進行聲明,讓調用者來處理該異常。關鍵字throws運用在方法聲明上,用來表示目前方法不處理異常,隻是提醒該方法的調用者來處理異常(也就是指:抛出異常)

聲明的格式:

修飾符 傳回值類型 方法名(參數) throws 異常類名1,異常類名2..[
		throw new 異常類名1("産生異常的原因");
		throw new 異常類名2("産生異常的原因");
		...
}

使用throws關鍵字注意;

注意;
1.throws 關鍵字必須寫在方法聲明上
2.throws 關鍵字後面聲明的異常必須是Exception或者是其的子類
3.在方法的内部若是抛出了多個異常類對象,
		那麼throws後面必須也聲明對應的多個異常類
			如果抛出的多個異常對象之間有着子父類的關系,
							那麼就直接聲明父類異常就行,
4.如果調用了一個聲明了批出異常的方法,那麼就必須要處理該方法聲明的異常
	要麼繼續使用throws聲明抛出異常交給方法的調用者來處理,
			依次往上抛出,直到最終抛出給JVM來處理
	要麼就使用try...catch自己來處理這個異常。
           

使用throws關鍵字來抛出異常有個缺點,就是當使用throws抛出一個異常時,那麼産生了該異常的代碼之後的後續代碼就不會在執行了,因為JVM已經中斷處理了。

4、try-catch捕獲異常

使用try-catch的結構方式就是用來捕獲異常。

  • 捕獲異常:捕獲異常就是指Java中對異常有着針對性的語句來進行捕獲異常,并且可以對出現的異常進行指定方式的處理。
使用throws關鍵字聲明的方法,不處理異常,而是将出現的異常抛出給方法的調用者來處理;
使用try-catch語句可以處理異常,對出現的異常以指定的方法來處理
使用格式 1:處理一個異常
 try{
  //可能會出現異常的代碼塊
}catch(定義異常變量,用于接收try中的異常對象){
  //産生異常對象後,對異常進行處理的邏輯,一般會記錄到一個日志中
}

使用格式 2:處理多個異常

 try{
  //可能會出現異常的代碼塊
}catch(定義異常變量1,用于接收try中的異常對象1){
  //産生異常對象後,對異常進行處理的邏輯,一般會記錄到一個日志中
}catch(定義異常變量2,用于接收try中的異常對象2){
  //産生異常對象後,對異常進行處理的邏輯,一般會記錄到一個日志中
}catch(定義異常變量3,用于接收try中的異常對象3){
  //産生異常對象後,對異常進行處理的邏輯,一般會記錄到一個日志中
}
...


使用格式 3:處理多個異常,并且最終無論有無異常産生都會執行一個代碼塊
 try{
  //可能會出現異常的代碼塊
}catch(定義異常變量1,用于接收try中的異常對象1){
  //産生異常對象後,對異常進行處理的邏輯,一般會記錄到一個日志中
}
...
catch(定義異常變量3,用于接收try中的異常對象3){
   //産生異常對象後,對異常進行處理的邏輯,一般會記錄到一個日志中
}finally{
   //無論是否出現異常,都會執行的代碼塊
}
注意: 
finally不能獨立使用,必須要和try一起使用;
finally一般會用于對資源的釋放回收處理,程式無論是否會出現異常最終都要進行資源回收釋放處理。


           

使用try-catch注意;

  • 如果try中産生了異常,那麼就會執行catch中的異常處理邏輯,執行完catch中的處理邏輯,就會繼續執行try-catch之後的代碼。
  • 如果try中沒有産生異常,那麼就不會執行catch中異常的處理逐輯,執行完try中的代碼後,就會繼續執行try-catch之後的代碼。

5.Throwable類中處理異常的3個方法

String getMessage():  傳回throwable類異常對象的簡單概述。
String tostring()  :  傳回throwabLe類的異常對象較長的描述資訊(字元串)。
void printStackTrace() :
            	JVM列印異常對象的方法,列印的異常資訊是最全面的
           

6.使用異常的注意事項

(1)、當有多個異常使用捕獲時的處理方式:

  • 1.多個異常分别處理
  • 2.多個異常一次性捕獲,然後分别處理(一次捕獲,多次處理)
  • 3.多個異常一次性捕獲,一次性處理(捕獲一次,處理一次)

舉例說明:

//1.多個異常分别處理
//處理異常1
try{
          //定義一個數組下标越界異常
          int[]  ints={1,2,3,4,5,6};
          int anInt = ints[6];
          System.out.println(anInt);
          //ArrayIndexOutOfBoundsException: 6

      }catch (ArrayIndexOutOfBoundsException e){
          System.out.println(e);
      }
//處理異常2
try{
        //定義一個集合下标越界異常
        ArrayList<Integer> integers = new ArrayList<>();
        integers.add(1);
        integers.add(2);
        integers.add(3);
        integers.add(4);
        integers.add(5);
        integers.add(6);
        Integer integer = integers.get(6);
        System.out.println(integer);
        //IndexOutOfBoundsException: Index: 6, Size: 6
    }catch (IndexOutOfBoundsException e){
        System.out.println(e);
    }
           
// 2.多個異常一次性捕獲,然後分别處理(一次捕獲,多次處理)
try{
    //定義一個數組下标越界異常
    int[]  ints={1,2,3,4,5,6};
    int anInt = ints[6];
    System.out.println(anInt);
    //ArrayIndexOutOfBoundsException: 6

    //定義一個集合下标越界異常
    ArrayList<Integer> integers = new ArrayList<>();
    integers.add(1);
    integers.add(2);
    integers.add(3);
    integers.add(4);
    integers.add(5);
    integers.add(6);
    Integer integer = integers.get(6);
    System.out.println(integer);
    //IndexOutOfBoundsException: Index: 6, Size: 6
}catch (ArrayIndexOutOfBoundsException e){
    System.out.println(e);
}catch (IndexOutOfBoundsException e){
    System.out.println(e);
}
/*
* 使用一次捕獲多次處理時要注意:
* 1.如果catch裡面定義的異常變量之間有着子父類的關系,
*     那麼子類的異常就必須要寫在父類之上,否則try中抛出的異常對象
*     系統會由上向下執行catch來捕獲這個異常并處理異常,預設會處理父類異常而不會處理子類異常
*    例如: ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException
* */
           
//3.多個異常一次性捕獲,一次性處理(捕獲一次,處理一次)
try{
    //定義一個數組下标越界異常
    int[]  ints={1,2,3,4,5,6};
    int anInt = ints[6];
    System.out.println(anInt);
    //ArrayIndexOutOfBoundsException: 6
    //定義一個集合下标越界異常
    ArrayList<Integer> integers = new ArrayList<>();
    integers.add(1);
    integers.add(2);
    integers.add(3);
    integers.add(4);
    integers.add(5);
    integers.add(6);
    Integer integer = integers.get(6);
    System.out.println(integer);
    //IndexOutOfBoundsException: Index: 6, Size: 6
} catch (IndexOutOfBoundsException e){
    System.out.println(e);
}
           

(2)、子父類異常的注意事項

  • 如果父類抛出了多個異常,那麼子類在重寫父類方法時就必須要抛出和父類相同的異常 或者父類異常的子類 或者不抛出異常
  • 如果父類方法中沒有抛出異常,那麼子類重寫父類方法時,就也不能批出異常。若子類此時産生了異常那麼隻能捕獲處理try-catch,而不能聲明批出異常。
public class fuClass {
    //function1抛出多個異常
    public void function1() throws NullPointerException,IndexOutOfBoundsException{}
    //function2抛出多個異常
    public void function2() throws NullPointerException,IndexOutOfBoundsException{}
    //function3抛出多個異常
    public void function3() throws NullPointerException,IndexOutOfBoundsException{}
    //function4沒有抛出異常
    public void function4(){}
}
class ziClass extends fuClass {
       // 重寫方法,抛出與父類相同的異常
        public void function1() throws NullPointerException,IndexOutOfBoundsException{}
        //重寫方法,抛出父類異常的子類異常
        public void function2() throws StringIndexOutOfBoundsException{}
        //重寫方法,不批出異常
        public void function3(){}
/*
如果父類方法中沒有抛出異常,那麼子類重寫父類方法時,就也不能批出異常。
若子類此時産生了異常那麼隻能捕獲處理try-catch,而不能聲明批出異常。*/
        public void function4(){
            try{
                //可能出現異常代碼
            }catch (ArrayIndexOutOfBoundsException e){
                //自己處理異常
            }
        }
        
}
           

五、自定義的異常類

        自定義異常也就是自己定義一個異常來滿足目前代碼的需求

自定義異常類格式1:
//自定義編譯時期的異常類,若方法内部抛出了異常,
//  那麼方法調用者就要處理這個異常 try-catch  或者 throws
public class XXXException extends Exception {
		//添加無參構造方法
		//添加帶異常資訊的構造方法
}

自定義異常類格式2:
//自定義運作時期的異常類,若方法内部抛出了異常,
//那麼方法不需要處理異常,而是把異常抛JVM來處理(中斷處理)
public class XXXException extends RuntimeException {
		//添加無參構造方法
		//添加帶異常資訊的構造方法
}


           

制作不易,各位友友們,大佬們給點鼓勵!

點贊👍 👍 👍 收藏+關注 一鍵三連走起!