1. 程式人生 > >《瘋狂Java講義(第4版)》-----第10章【異常處理】

《瘋狂Java講義(第4版)》-----第10章【異常處理】

異常處理可以提高程式的健壯性、呈現功能給使用者更加友好。Java異常機制主要關鍵字:try、catch、finally、throw、throws。throws關鍵字在宣告方法時候使用,用於宣告該方法可能丟擲的異常。而throw關鍵字用於丟擲一個實際的異常。Java把異常分為兩種,Checked異常(可以在編譯階段被處理的異常)和Runtime異常,強制程式處理所有的Checked異常。

異常處理機制

try…catch捕獲異常

下面程式碼中,try塊裡面如果有異常,系統就生成一個異常物件,交給Java執行時環境,這就時丟擲異常。Java執行時環境收到異常物件後,去找能處理該異常的catch塊,交給相應的catch塊處理異常,這就是捕獲異常。如果無法找到處理該異常的catch塊,執行時環境終止,Java程式退出。

try{
	//業務程式碼
}catch(Exception e){
	//處理異常
}

注意:try塊和catch塊僅有一句程式碼時花括號也不可以省略。try塊裡定義變數是try塊的區域性變數,其他部分的程式無法訪問。

Java異常類的繼承關係

在這裡插入圖片描述 Error錯誤一般是指與虛擬機器有關的問題,如系統崩潰、虛擬機器錯誤、動態連結失敗等,這種錯誤無法恢復或不可捕獲,將會導致程式中斷。try…catch捕獲的異常是Exception類的。

【捕獲處理異常示例程式碼】 注意捕獲異常的catch塊的順序,先捕獲小異常,再捕獲大異常,否則編譯報錯。

public class Hello{
	
	
	public static void main(String[] args){
		
		try{
			int a = Integer.parseInt(args[0]);
			int b = Integer.parseInt(args[1]);
			int c = a / b;
			System.out.println("您輸入的兩整數相除的商是: "+c);
		}catch(IndexOutOfBoundsException ie){
			System.out.println("輸入的引數個數小於2,陣列越界!");
		}catch(NumberFormatException ne){
			System.out.println("數字格式不正確,輸入的引數應該是整數");
		}catch(ArithmeticException ae){
			System.out.println("算術異常");
		}catch(Exception e){
			System.out.println("未知異常");
		}
		
	}
}

在這裡插入圖片描述

Java7新增的多異常捕獲

捕獲多種異常時,用 | 隔開,異常變數預設用了隱式的final修飾,不能對異常變數重新賦值。

public class Hello{
	
	
	public static void main(String[] args){
		
		try{
			int a = Integer.parseInt(args[0]);
			int b = Integer.parseInt(args[1]);
			int c = a / b;
			System.out.println("您輸入的兩整數相除的商是: "+c);
		}catch(IndexOutOfBoundsException | NumberFormatException | ArithmeticException e){
			System.out.println("陣列越界、數字格式不對或算術異常");
			//編譯報錯,異常變數預設有final修飾,不可重新賦值
			//e = new IndexOutOfBoundsException();
		}catch(Exception e){
			System.out.println("未知異常");
			e = new Exception();//這是正確的,不是多異常捕獲,異常變數沒有final隱式修飾
		}
		
	}
}

訪問異常資訊

所有的異常都有獲取或列印異常資訊的方法,檢視他們繼承的父類Throwable就知道了,檢視官方文件如下: 在這裡插入圖片描述

public class Hello{
	
	
	public static void main(String[] args){
		
		try{
			int a = Integer.parseInt(args[0]);
			int b = Integer.parseInt(args[1]);
			int c = a / b;
			System.out.println("您輸入的兩整數相除的商是: "+c);
		}catch(IndexOutOfBoundsException | NumberFormatException | ArithmeticException e){
			System.out.println("陣列越界、數字格式不對或算術異常");
			System.out.println(e.getMessage());
			e.printStackTrace();
			
		}catch(Exception e){
			System.out.println("未知異常");
			
		}
		
	}
}

在這裡插入圖片描述

使用finally回收資源

  • try塊裡如果打開了物理資源(比如資料庫連線、網路連線、磁碟檔案等),需要顯式回收,Java的垃圾回收機制不回收物理資源,只回收堆記憶體中的物件佔用的記憶體。
  • 不管try塊的程式碼是否有異常,不管catch塊是否被執行,甚至try塊、catch塊中執行了return語句,finally塊總會被執行(有一種特例:在catch塊執行System.exit(1)退出虛擬機器,finally塊就不執行了)。有try塊的話,catch塊和finally塊必須至少有其一。示例程式碼見該書375頁。
  • 一般不要在finally塊中使用return語句或throw語句,一旦finally塊中使用了return語句或throw語句,會導致try塊、catch塊的return、throw語句失效。因為,try塊、catch塊遇到return、throw語句的時候就會找finally塊,如果沒有finally塊,就執行return或throw語句結束方法,如果有finally塊,就先去執行finally塊,再跳回到執行try塊、catch塊程式碼,而如果finally塊裡有return語句或throw語句把方法結束掉了,那就跳不回去了!示例程式碼見該書376頁。

異常處理巢狀

try、catch、finally三個塊中都可以進行try…catch…finally巢狀,沒有特別限制。

Java7自動關閉資源的try語句

與375頁關閉資源語句對比,377頁Java7自動關閉資源的方法更加簡潔。具體看377頁講解部分及示例程式碼。

Checked異常與Runtime異常

  • Runtime異常:所有Runtime類及其子類的例項
  • Checked異常:非Runtime異常 對於程式中的Checked異常,Java要求必須顯式捕獲或者顯式宣告丟擲該異常。

使用throws宣告丟擲異常

使用throws宣告丟擲異常的思路是:當前方法不處理異常,交給上一級呼叫者處理;如果main方法也不知道怎麼處理異常,交給JVM處理。JVM處理異常的方式是:列印異常的跟蹤棧資訊,終止程式執行。

程式中使用了throws宣告丟擲異常,就表明本級方法不處理該異常,讓上一級呼叫者處理,就不需要再用顯示的try…catch捕獲異常了(筆者試了一下,同時用也行!!)。

方法重寫時,子類方法宣告丟擲的異常應該比父類宣告丟擲的異常型別小或相同。

使用throw丟擲異常

程式出錯的時候,系統會自動丟擲異常;除此之外,系統也允許程式用throw語句自行丟擲異常。注意throw丟擲的異常類例項,與throws宣告丟擲異常類不同。

如果throw語句丟擲的時Checked異常,該throw語句要麼用try塊顯式處理,要麼放在一個帶throws宣告丟擲的方法中。如果throws語句丟擲的是Runtime異常,該throw語句可以放在try塊或宣告丟擲的方法中,也可以完全不理會該異常。示例程式碼見381頁。

自定義異常見382頁383頁示例程式碼

異常鏈見385頁386頁

Java的異常跟蹤棧printStackTrace見386頁387頁