Java異常處理的兩種方式


異常處理方式一:在當前方法中直接用try…catch處理

異常處理方式二:在當前方法中不處理,throws 異常拋給調用者處理

1 方式1:try…catch...finally捕獲異常

1.1 try…catch代碼塊

try-catch的方式就是捕獲異常。

  • try:該代碼塊中編寫可能產生異常的代碼。

  • catch:用來進行某種異常的捕獲,對捕獲到的異常進行處理。

格式:

//形式一:一個catch塊
try{
    可能發生異常的代碼(沒有異常的代碼也可以放進來)
}catch(異常類型  異常名e){
    處理異常的代碼(一般都是打印異常的信息的語句)
}

//形式二:多個catch塊
try{
    可能發生異常的代碼
}catch(異常類型  異常名e){
    處理異常的代碼(一般都是打印異常的信息的語句)
}catch(異常類型  異常名e){
    處理異常的代碼(一般都是打印異常的信息的語句)
}
...
catch(異常類型  異常名e){
    處理異常的代碼(一般都是打印異常的信息的語句)
}

try 和 catch 都不能單獨使用

注意:

  • catch 中定義的異常變量的類型是根據 try 中拋出的異常來定義的;一般拋出什么類型的異常對象,就定義什么類型異常變量來接收這個異常對象
  • try 中可能會拋出多個異常對象,就可以定義多個 catch 來分別處理這些異常對象
  • try代碼中如果出現了異常,那么就不會繼續執行 try 中的代碼,找對應的匹配的catch分支執行,執行完畢后繼續執行try...cath之后的代碼
  • try代碼中如果沒有出現異常,正常執行try中的代碼,不會執行catch中異常的處理邏輯,會執行執行try...catch之后的代碼
  • 多個異常該如何處理呢

    1. 多個異常分別處理,一個異常對應一個try一個catch
    2. 多個異常一次捕獲多次處理,一個try多個catch
    3. 多個異常一次捕獲一次處理,只用一個try一個catch,定義一個范圍更大的父類異常對象

    一般我們是使用一次捕獲多次處理方式,格式如下:

    try{
         編寫可能會出現異常的代碼
    }catch(異常類型A  e){
         處理異常的代碼
         //記錄日志/打印異常信息/繼續拋出異常
    }catch(異常類型B  e){
         處理異常的代碼
         //記錄日志/打印異常信息/繼續拋出異常
    }...
    

注意:這種異常處理方式,要求多個catch中的異常不能相同,並且若catch中的多個異常之間有繼承關系,那么要求子類異常在上面的catch處理,父類異常在下面的catch處理;若無繼承關系,順序隨意。

演示如下:

public class ExceptionDemo {
    public static void main(String[] args) {
        try {
            show(1);
        }catch (NullPointerException e) {
            System.out.println("處理空指針異常");
        }catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("處理數組下標越界異常");
        }
        System.out.println("程序結束!");
    }

    private static void show(int a) {
        if (a == 0) {
            int[] arr = new int[0];
            System.out.println(arr[1]);
        }else {
            int[] arr = null;
            System.out.println(arr.length);
        }
    }
}

1.2 finally 代碼塊

finally:有一些特定的代碼無論異常是否發生,都需要執行。另外,因為異常會引發程序跳轉,導致有些語句執行不到。而finally就是解決這個問題的,在finally代碼塊中存放的代碼都是一定會被執行的。

什么代碼必須最終執行?

當我們在try語句塊中打開了一些物理資源(磁盤文件/網絡連接/數據庫連接等),我們都得在使用完之后關閉打開的資源。

格式:

//形式一:try...catch...finally
try{
    可能發生異常的代碼
}catch(異常類型  異常名e){
    處理異常的代碼(一般都是打印異常的信息的語句)
}
...
catch(異常類型  異常名e){
    處理異常的代碼(一般都是打印異常的信息的語句)
}
finally{
    無論try中是否有異常,也不管catch是否可以捕獲異常,也不管try和catch中是不是有return,都要執行的部分
}

//形式二:try...finally(一般不用)
try{
    可能發生異常的代碼
}finally{
    無論try中是否有異常,也不管是不是有return,都要執行的部分
}

注意:finally不能單獨使用

finally代碼參考如下:

public class ExceptionDemo2 {
    public static void main(String[] args) {
        try {
            show(1);
        }catch (NullPointerException e) {
            System.out.println("處理空指針異常");
        }catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("處理數組下標越界異常");
        }finally {
            System.out.println("finally中的方法一定會執行");
        }
        System.out.println("程序結束!");
    }

    private static void show(int a) {
        if (a == 0) {
            int[] arr = new int[0];
            System.out.println(arr[1]);
        }else {
            int[] arr = null;
            System.out.println(arr.length);
        }
    }
}

當只有在try或者catch中調用退出JVM的相關方法,finally才不會執行,否則finally永遠會執行。

finally與return混用的情況(避免使用)

  • 不管try中是否發生異常,也不管catch是否可以捕獲異常,也無論try或catch中是否有return語句,finally中的代碼都必須執行
  • 如果finally中有return,就從finally塊的的return返回。
  • 如果finally中沒有return,那么先把try或catch中該執行的執行完(包括把返回值的結果放到要帶回調用處的操作數棧的位置)

演示代碼:

public class ExceptionDemo3 {
    public static void main(String[] args) {
        int num = getNum(4);
        System.out.println(num); // 0
    }

    private static int getNum(int a){
        int result = 10;
        try{
            System.out.println(a/0);
            if(a > 0){
                result = 20;
                return result;
            }else if(a < 0){
                result = -20;
                return result;
            }else{
                return result;
            }
        }catch(Exception e){
            System.out.println("exception");
            result = 0;
            return result;
        }finally{
            result = 30;
            System.out.println("finally");
//			return result;//如果有這句,結果就變成30
        }
    }
}

return 值; 語句有兩個動作:

(1)把返回值放到”操作數棧“中

(2)結束當前方法的執行,把“操作數棧”中的值會返回給調用處

如果finally中沒有return,finally中的語句會執行,但是不影響最終的返回值
即try、catch中的return語句兩步拆開走,先把把返回值放到“操作數棧”中,然后走finally中的語句,最后結束當前方法,把這個“操作數棧”中的值返回給調用處

2 方式2:throws聲明拋出異常

2.1 throw關鍵字

在編寫程序時,我們必須要考慮程序出現問題的情況。比如,在定義方法時,方法需要接受參數。那么,當調用方法使用接受到的參數時,首先需要先對參數進行合法的判斷,數據若不合法,就應該告訴調用者,傳遞合法的數據進來。這時需要使用拋出異常的方式來告訴調用者。

異常的對象的創建和拋出有兩種方式:

(1)JVM創建並拋出

(2)程序員new出來,然后由throw拋出。

在java中,提供了一個throw關鍵字,它用來拋出一個指定的異常對象:

  1. 創建一個異常對象。封裝一些提示信息(信息可以自己編寫)

  2. 通過關鍵字throw,throw 異常對象,將這個異常對象告知給調用者

throw 用在方法內,用來拋出一個異常對象,將這個異常對象傳遞到調用者處,並結束當前方法的執行。
注意事項:
throw關鍵字必須寫在方法內部
throw關鍵字后邊創建的異常對象,必須是Exception或Exception的子類對象
throw關鍵字后邊創建的異常對象:
(1) 如果是運行期異常,那么我們不用處理這個異常,交給JVM處理,默認處理方式就是中斷處理
(2) 如果是編譯期異常,那么我們就必須處理這個異常,要么throws繼續拋出交給上層調用者處理,要么try...catch自己處理
使用格式:

throw new 異常類名([參數]);

例如:

throw new Exception();

throw new ClassNotFoundException("類型不存在!");

代碼示例:

public class ThrowsDemo {
    public static void main(String[] args) throws ClassNotFoundException, FileNotFoundException {
        method01(0);
    }

    private static void method01(int a) throws ClassNotFoundException, FileNotFoundException {
        if (a == 0){
            throw new ClassNotFoundException("類型不存在!");
        }else {
            throw new FileNotFoundException("文件不存在!");
        }
    }
}

那么對於調用者來說,該怎么處理呢?

對於運行期異常可以不做處理;對於編譯期異常:一種是使用 try...catch 進行捕獲處理,另一種就是使用throws關鍵字繼續將異常聲明出去,由方法調用者處理

2.3 throws關鍵字

聲明異常:將問題標識出來,報告給調用者。如果方法內拋出了編譯期異常,而沒有捕獲處理,那么必須通過throws關鍵字進行聲明,讓調用者去處理。

關鍵字throws用在方法聲明上,用於表示當前方法不處理異常,而是提醒該方法的調用者來處理異常

聲明異常格式:

修飾符 返回值類型 方法名(參數) throws xxxException, yyyException...{
	...
}

聲明異常的代碼示例:

public class ThrowsDemo {
    public static void main(String[] args) throws NullPointerException, ArrayIndexOutOfBoundsException {
        int[] arr = null;
        method01(arr);
    }

    private static void method01(int[] arr) throws NullPointerException, ArrayIndexOutOfBoundsException {
        //Objects.requireNonNull(arr);

        if (arr.length==0){
            throw new ArrayIndexOutOfBoundsException("越界了");
        }

        if (arr == null){
            throw new NullPointerException();
        }

    }
}

注意事項:

  • throws關鍵字必須寫在方法聲明處
  • throws關鍵字后邊聲明的異常類名必須是Exception或Exception的子類
    一般方法內部拋出什么異常類型,就聲明什么異常對象
  • 如果方法內部拋出了多個異常對象,那么在throws后面可以寫多個異常類,用逗號隔開。
    如果拋出的多個異常對象有子父類關系,那么我們聲明父類異常即可
  • 如果調用了一個聲明拋出編譯期異常的方法,那么我們就必須處理這個異常對象:
    a.可以使用throws繼續聲明拋出這個異常,最終交由JVM處理 --> 中斷處理
    b.可以使用try...catch自己處理這個異常
  • 運行期異常可以不處理,即不捕獲也不聲明拋出,交給JVM處理(中斷))
  • 如果父類拋出了多個異常,子類重寫父類方法時,拋出和父類相同的異常或者是父類異常的子類或者不拋出異常。
  • 父類方法沒有拋出異常,子類重寫父類該方法時也不可拋出異常。如果子類產生異常,只能捕獲處理,不能聲明拋出


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM