java之異常處理

概述:在程序設計和運行的過程中,發生錯誤是不可避免的,儘管我們去儘量的減少錯誤的產生,但是總會有我們沒有預料到的錯誤。比如說,我們在程序開發中使用的if-else語句,其實這個就是處理異常的過程,但是這對於代碼龐大的程序來說會有一些問題,比如說,代碼臃腫:業務代碼和異常處理代碼放一起,程序員要花很大精力堵漏洞,程序員很難堵住所有“漏洞”。所以,java提供了異常處理機制來幫助程序員檢查可能出現的錯誤,它將異常處理代碼與業務代碼分離,java將異常封裝到一個類中,出現錯誤時,會拋出異常,這樣保證了程序的可讀性和可維護性。當然,異常處理機制也存在一些弊端,比如使用異常處理可能會降低程序的執行效率,增加語法複雜度等。

目錄

一、異常的分類

    1、Error——系統錯誤

     2、Exception——異常

     (1)、運行時異常

     (2)、非運行時異常

二、異常處理

    1、捕捉處理異常

        (1)、try...catch...finally代碼塊

    2、在方法中拋出異常

        (1)、使用throws關鍵字拋出異常

        (2)、使用throw關鍵字拋出異常

三、自定義異常

四、異常的使用原則


 

一、異常的分類

       java類庫的每一箇中都定義了異常類,所以這些類都是Throwable類的子類。Throwable類派生了兩個子類,分別是Error類和Exception類,其中,Error類及其子類用來描述java運行系統中的內部錯誤以及資源耗盡的錯誤,這類錯誤比較嚴重。Exception類稱爲非致命性類,可以通過捕捉處理使程序繼續執行。Exception類又可以根據錯誤發生的原因分爲運行時異常和非運行時異常。

       1、Error——系統錯誤

            Error類及其子類通常用來描述java運行系統中的內部錯誤,該類定義了常規環境下不希望由程序捕獲異常,例如ThreadDeath等,這些錯誤發生時,java虛擬機(JVM)一般會選擇線程終止。

從圖中我們可以看到顯示的異常信息是"java.lang.Error",這說明這是一個系統錯誤,程序遇到這種錯誤通常會停止執行,並且,這類錯誤無法使用異常語句處理。

       2、Exception——異常

            Exception是程序可以處理的異常,這種異常主要分爲運行時異常和非運行時異常,程序中應當儘可能去處理執行異常。

            (1)、運行時異常

                    運行時異常是程序運行過程中產生的異常,它是RuntimeException類及其子類異常。這些異常一般是由程序員邏輯錯誤引起的,程序應該從邏輯角度儘可能避免這類異常的發生。下表羅列了 java提供了常見的RuntimeException異常。

異常類 說明
ClassCastException 類型轉換異常
NullPointException 空指針異常
ArrayIndexOutOfBoundsException 數組下標越界異常
ArithmeticException 算術異常
ArrayStoreException 數組中包含不兼容的值拋出的異常
NumberFormatException 字符串轉換爲數字拋出的異常
IllegalArgumentException 非法參數異常
FileSystemNotFoundExcetion 文件系統未找到異常
SecurityException 安全性異常
StringIndexOutOfBoundsException 字符串索引超出範圍拋出的異常
NegativeArraySizeException 數組長度爲負異常

            (2)、非運行時異常

                 非運行時異常是RuntimeException類及其子類異常以外的異常。這類異常是必須要處理的異常,如果不處理,程序就不能編譯通過。

異常類 說明
ClassNotFoundException 未找到相應類異常
SQLException 操作數據庫異常類
IOException 輸入/輸出流異常
TimeoutException 操作超時異常
FileNotFoundException 文件未找到異常

二、異常處理

       1、捕捉處理異常

           (1)、try...catch...finally代碼塊

                        try...catch代碼塊主要用來對異常進行捕捉並處理。在實際使用時,該代碼塊還有一個可選的finally代碼塊。標準語法如下:

try{
    //程序代碼塊
}
catch(Exceptiontype e)
    //對Exceptiontype的處理
}
finally{
    //代碼塊
}

       try代碼塊是可能發生異常的java代碼;catch代碼塊在try代碼塊之後,用來激發被捕獲的異常;finally代碼塊是異常處理結構的最後執行部分,無論程序是否發生異常,finally代碼塊中的代碼都將被執行,所以在finally代碼塊中通常放一下釋放資源、關閉對象的代碼。

案例:



public class TryCatchFinally {   //創建類
	
	public static void main(String[] args) {
		try {                               //try語句中包含可能出現異常的程序代碼
			String str = "Tom";
			System.out.println(str + ",");
			int age = Integer.parseInt("x");//數據類型轉換
			System.out.println(age+"歲了");
		}catch(Exception e) {               //catch代碼塊用來獲取異常信息,Exception是try代碼塊傳遞給catch代碼塊的類型,e是對象名
			e.printStackTrace();            //輸出異常性質
		}
		finally {
			System.out.println("program over");
		}
	}
}

運行結果如下: 

       我們可以看到,程序依然可以運行,沒有因爲異常而終止。當try代碼塊中的語句發生異常時,程序就會跳轉到catch代碼塊中執行,執行完catch代碼塊中的程序代碼後,將繼續執行catch代碼塊後的其他代碼塊,而不會執行try代碼塊中發生異常語句後面的代碼。

       上面代碼中,在catch代碼塊中使用了Exception對象的printStackTrace()方法輸出了異常的棧日誌。除了這個以外,還有三個常用方法:

       (1)getMessage()方法:獲取有關異常事件的信息

       (2)toString()方法:獲取異常的類型與性質

       (3)printStackTrace()方法:獲取異常事件發生時執行堆棧的內容

       無論程序中有無發生異常,finally代碼塊中的代碼一般情況下都會正常執行。除非以下三種情況:

       (1)在finally代碼塊中發生異常

       (2)在前面的代碼中使用了System.exit() 退出程序

       (3)程序所在的線程死亡

     2、在方法中拋出異常

         (1)、使用throws關鍵字拋出異常

          throws關鍵字通常被應用在聲明方法中,用來指定方法可能拋出的異常,多個異常可使用逗號分隔。

          格式:

返回值類型  方法名(參數列表)  throws 異常類型名{
      //方法體
}

案例:



public class TestThrows {
    static void test() throws ArrayIndexOutOfBoundsException{//定義方法並拋出數組下標越界異常
		
    	int[] arr = new int[2];
		
		for(int i=0;i<10;i++)
		{
			arr[i]=i;
		}
	}
	public static void main(String[] args) {
		
		try {
			test();  //調用方法
		}catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("test()方法拋出異常");//輸出異常信息
		}
	}
}

運行結果 :

       指得注意的是:當使用throws爲方法拋出異常時,如果子類繼承父類,子類重寫方法拋出的異常也要和原父類方法拋出的異常相同或是其異常的子類,除非throws 異常時RuntimeException

       (2)、使用throw關鍵字拋出異常

          throw關鍵字通常用在方法體中“製造”一個異常,程序在執行到throw語句時立即終止,它後面的語句都不執行。throw語句通常用於程序出現某種邏輯錯誤時,由開發者主動拋出某種特定類型的異常。

         格式:

throw new 異常類型名(異常信息)

案例:



public class TestThrow {
   
	public static void main(String[] args) {
		
		int num = 5;
		int result;
		
		for(int i=0;i<5;i++)
		{
			if(i==0)
			{
				throw new ArithmeticException("除數不能爲0");//拋出算術異常
			}
			result = num/i;
			System.out.println("result = "+result);
		}	
	}
}

運行結果:

        throw與throws的區別:

                 1、throws用在方法聲明後面,表示拋出異常,由方法的調用者處理,而throw用在方法體內,用來製造一個異常,由方法體內的語句處理。

                 2、throws是聲明這個方法會拋出這種類型的異常,以便使它的調用者知道要捕獲這個異常,而throw是直接拋出一個異常實例。

                3、throws表示出現異常的一種可能性,並不一定會發生,如果使用throw,就一定會產生某種異常

三、自定義異常

         在程序中,可能會遇到使用java內置異常類也無法處理的異常情況,比如說,年齡爲負等。這個時候就需要我們自定義異常類。自定義異常類只需從Exception類或它的子類派生一個即可,如果我們自定義異常類繼承Exception類,則必須對其進行處理,如果不想處理,可以繼承RuntimeException類。習慣上,自定義異常類應該包含兩個構造器,一個默認構造器,一個包含有詳細新的構造器。

案例:



public class CustomException {
	public static void main(String[] args) {
		
		TestAge t = new TestAge();
		
		t.setAge(-10);
	}

}

class TestAge{
	private int age;
	
	public int getAge() {
		return age;
	}
	
	public void setAge(int age) {
		if(age<0)
		{
			throw new MyException("年齡不能爲負數");
		}
		this.age = age;
	}
}

class MyException extends RuntimeException{//繼承RuntimeException類,如果繼承了Exception類,必須進行處理,就不能僅使用throw
	
	public MyException() {  //默認構造器
	}
	
	public MyException(String erms) { //帶有詳細信息的構造器,信息存儲在erms中
		super(erms);
	}
}

 四、異常的使用原則

 1、不用過度使用異常。雖然通過異常可以增強程序的健壯性,但是如果過度使用不必要的異常處理,可能會影響程序的執行效率。

 2、不要使用過於龐大的try...catch塊,在一個try塊中放置大量的代碼,會造成try塊中出現異常的可能性大大增加,也會使異常原因的分析困難加大。

 3、避免使用catch(Exception e)。如果所有異常都採用相同的處理方式,將導致無法對不同異常的分情況處理;另外,這種捕獲方式可能將程序中的全部錯誤、異常捕獲,如果這是出現一個關鍵錯誤,可能會被忽略掉。

 4、不要忽略捕捉到的異常,遇到異常要及時處理。

 5、如果父類拋出多個異常,則覆蓋方法必須拋出相同的異常或其異常的子類,不能拋出新的異常。

 

 

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