異常1——初識(Java)

在編程過程中,我們所寫的代碼會遇到很多問題,有些語法上的錯誤或是邏輯上的錯誤我們都是可以在編譯之後或是運行之後進行更改的,然而有些錯誤是不知道什麼時候出錯,在編譯過程中我們發現了也不能更改的錯誤。那麼這個時候我們就要做相應的處理,以確保一個程序能繼續運行。

先來看一個例子:

我們發現在打印10/0這個結果的時候,編譯時並沒有報錯,但是運行時出現了ArithmeticException這樣的一個異常,並且程序就停止了,這樣如果該句後面還有其他代碼語句的話,就不會被執行到。當然在我們編寫代碼的過程中,不僅僅只是這一個異常,還有很多其他的異常,如在介紹數組時出現的ArrayIndexOutOfBoundsException(數組角標溢出異常)、在介紹String類時出現的StringIndexOutOfBoundsException(字符串角標溢出異常)和遞歸時出現的StackOverFlowError(棧溢出錯誤),可見異常也是分好多種類的,相應的也有它相應的體系

但是不管分多少中異常或是錯誤,都是以Exception或者Error結尾的。隨機打開一個出現的異常的源碼,向上翻找,發現他的最終父類都是Throwable這個類,這個類還實現了其他的接口,並沒有繼承其他類。翻看該類的API,我們發現:

它的直接子類就只有Exception和Error這兩個類,因此可知運行時出現的錯誤打印的異常或者錯誤都是從這兩個子類繼承過來的。那麼這兩個到底是什麼呢?

Error:是由虛擬機直接拋出的嚴重性錯誤(內存中的問題), 因爲我們不能解決內存中的問題,但這在編譯時或者運行中是不會出現的,而是在運行之後出現的錯誤,一旦出現這種錯誤,我們在編譯時或者運行中是無法解決的,因此要在運行後,根據虛擬機出現的錯誤去改寫我們所寫的代碼,而不能進行捕獲。

Exception:是指一般性的錯誤,可以由虛擬機直接拋出,但是不建議這樣做,如果是在編譯時出現這樣的異常,我們需要向上聲明或是捕獲,在運行後出現這樣的異常,一般改代碼的語句或是進行捕獲。

而在Exception中,它的實現子類也有很多,如:

這麼多類中可以分爲兩大類:RuntimeException類和Exception及其其他子類。

RuntimeException類:運行時異常,想處理就處理,如果不處理則程序中斷;

Exception及其其他子類 :編譯時異常,需要被處理。

那麼如何對異常進行處理,Java提供兩種解決的辦法:1.聲明異常,事先告知調用者該函數內部可能會出錯,然後由調用者自行決斷,通常聲明異常用throws 異常的類或者throw 異常的對象;2.捕獲異常,將該問題獲取到,然後自己進行處理,不再向上聲明。

public class Main {
	public static void main(String[] args) {
		
		int[] a=new int[10];
		int index=10;
		show(a,index);
	}
	public static void show(int[] a,int index){
       //方法一:聲明異常對象
            /*	if(a==null){
		     throw new NullPointerException("數組爲空");  //如果數組爲空,操作不當可能會出現空指針異常,這裏可以聲明一個空指針異常的對象,注意用到了new是對象,然後提示數組爲空
		}
		if(index<0||index>=a.length){
		     throw new ArrayIndexOutOfBoundsException(); //對數組的角標操作不當,會出現數組角標越界異常,在這裏可以聲明一個數組角標異常的對象,提示用戶可能會產生的結果
		}*/
      //方法二:捕獲異常,採用try...catch來進行捕獲
		try{   //try的意思是嘗試,這裏就是先讓它嘗試的去運行
			System.out.println(a[index]);
		}catch(ArrayIndexOutOfBoundsException e){  //一旦出現了數組角標的異常,然後進行抓捕
			System.out.println(a[0]);  //這是對抓捕到的異常的一個處理。
		}
	}
}

現在來看一下兩種方法對運行結果的差異:

通過結果可知,聲明的異常還是會被拋出,而且一旦有一個位置出現問題,就會停止整個代碼的運行,那麼還是說,我們的問題並沒有解決。那麼如果進行捕獲呢?

通過結果可以發現,進行捕獲的異常,如果對捕獲的異常進行了處理,那麼是不會影響後面代碼語句的執行的,除非遇到下一個沒有被捕獲的異常被強行停止,要麼就是正常運行結束。

通過兩個例子是說明捕獲比聲明好嗎?顯然並不是,我們發現,例子中處理的異常是在編譯時沒有報錯的,而是在運行時可能會出錯,這就是運行時異常。然後有些異常是我們不知道的,也不知道會有什麼異常,其是異常的名字可以由我們自己去定義,然後進行聲明。然而有些異常我們明知道不會出錯,但是編譯器在編譯時提出可能會出現錯誤,這個時候我們首選聲明,如:

File類是需要聲明異常的類,儘管加上了判斷該文件類是否存在,再決定是否創建該文件的語句,在編譯時仍然報錯,在這裏就要進行聲明或者捕獲異常,而在這裏向上聲明比捕獲要好,因爲我們已經在創建這個文件了,儘管創建失敗再運行一次即可,如果進行捕獲還是要繼續創建文件。注意,如果一個代碼中聲明的異常種類太多,我們可以直接聲明一個它最大的父類。

上面的例子可以向上聲明一個IOException解決:

因此,在進行異常的處理時,選擇聲明還是捕獲要看具體的代碼需求,以及分清他是編譯時異常還是運行時異常。

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