1. 程式人生 > >Java異常機制Throwable

Java異常機制Throwable

Java中異常的概念以及處理異常

在Java程式執行期間出現了一個錯誤,這個錯誤可能是由於檔案包含了錯誤資訊,或者是由於網路連接出現問題,也可以是因為使用了無效的陣列下標,或者是試圖使用一個沒有被賦值的物件引用而造成的,我們稱這樣的錯誤為異常。在出現異常時使用者期望程式能夠採用一些理性的行為。如果由於出現錯誤而使得程式操作沒有完成,這時程式應該:
  • 返回到一種安全狀態,並能夠讓使用者執行一些其他命令
  • 允許使用者儲存所有操作的結果,並以適當的方法終止程式,

異常類的結構體系

                         
從上圖中我們可以知道,所有的異常類都是由Throwable繼承下來的,但在下一層立即分為兩個分支:Error和Exception。
一、Error 1、Error類層次描述了Java執行時系統的內部錯誤和資源耗盡錯誤。對於這類錯誤是無法難通過程式來解決的,所以程式不應該丟擲這種型別的物件。如果出現了這樣的內部錯誤,除了通知給使用者,並盡力使程式安全地終止。當然這類情況是很少出現的 二、Exception 在設計Java程式時,Exception是我們需要重點關注的錯誤,在Java程式中Exception又可以分為兩類:Runtime Exception、其它異常如:IOException。 1、派生於Runtime Exception 的異常主要包含以下幾種情況 
  • 錯誤的型別轉換
  • 陣列訪問越界
  • 訪問空指標
2、不是派生於Runtime Exception的異常包含
  • 試圖在檔案尾部讀取資料
  • 試圖開啟一個錯誤格式的URL
  • 試圖根據給定的字串查詢Class物件,而這個字串表示的類並不存在
這裡總結一條:如果是出現RuntimeException,那麼就一定是自己的問題。 三、執行時異常和檢查性異常 1、在Java語言中將派生於Error或RuntimeException類的所有異常稱為執行時異常,這類異常我們可以不處理,當出現這個的異常時,總是由虛擬機器接管,比如:我們從來沒有人去處理過NullPointerException異常,它就是執行時異常,並且這種異常還是最常見的異常之一。執行時異常我們常見的有ClassCastException(類轉換異常)IndexOutOfBoundsException(陣列越界)
NullPointerException(空指標)ArrayStoreException(資料儲存異常,運算元組時型別不一致)還有IO操作的BufferOverflowException異常; 2、除了執行時異常,其它的異常都被稱為檢查性異常我們經常遇到的IO異常及sql異常就屬於檢查式異常。對於這種異常,Java編譯器要求我們必須對出現的這些異常進行catch 所以 面對這種異常不管我們是否願意,只能自己去寫一堆catch來捕捉這些異常。常見的查檢性異常有:FileNotFoundException 檔案不存在異常、SQLException SQL異常等。

丟擲和捕捉異常的方法

一、使用throws丟擲異常 1、使用throws丟擲異常的情況:
  • 呼叫一個丟擲已檢查異常的方法,如:FileInputStream構造器
  • 程式執行過程中發現錯誤,並且利用throw語句丟擲一個已檢查異常
  • 程式出現錯誤,如:a[-1]=0會丟擲一個ArrayIndexOutOfBoundsException這樣的未檢查異常
  • Java虛擬機器和執行時庫出現的內部異常。
public class A**Exception   {   
              private String id;   
              public void setID(String id)  throws IllegalException{
                          if(id.length() == 7) {  
                                 this.id = id;   
                         }else{   
                               throw new IllegalArgumentException("引數長度不是7位");   
                        }   
             }   
}  

上面的程式碼,表示就丟擲了一個IllegalArgumentException型別的異常,如果在一個方法體中丟擲了異常,那麼就希望呼叫者能夠去捕獲異常,在Java語言中可以通過throws來宣告某個方法可能會丟擲的異常,這樣就可以讓呼叫者明白該方法可能會出現什麼異常,要及時去捕獲。

二、使用try{....}catch(){....}finally{....}捕捉異常
 try{
        //執行的程式碼,其中可能有異常。一旦發現異常,則立即跳到catch執行。否則不會執行catch裡面的內容  
     }catch (Exception e) {
        //除非try裡面執行程式碼發生了異常,否則這裡的程式碼不會執行 
     }finally{
       //不管什麼情況都會執行,包括try catch 裡面用了return ,可以理解為只要執行了try或者catch,就一定會執行 finally 
     }
關於try...catch...finally方法的說明:
package com.exception;
public class TryCatchUse {
	public static void main(String[] args) {
	   try{
			System.out.println("try statement...");
			//Integer.valueOf("2");//沒有異常  
			Integer.valueOf("admin");//有異常
	     }catch (NumberFormatException e) {
			System.out.println("catch statement...");
			e.printStackTrace();//打印出異常資訊
	     }finally{
	    	System.out.println("finally statement...");
	     }
	     System.out.println("after finally statement...");
	}
}
a、如果try中沒有出現異常,那麼catch中的程式碼不會執行。執行完try中程式碼後直接執行finally中程式碼。 b、如果try中出現異常,就會停止執行try中的程式碼,直接跳到catch中執行其中程式碼,catch中程式碼執行完後,再執行finally中的程式碼。 c、如果沒有出現異常,但是try中存在return,或者是出現異常,但是catch中存在異常,這時finally後的程式碼都不會執行。 d、finally並不是捕獲異常的必須部分,當我們需要關閉一些由於異常而無法關閉的資源時需要用到finally。 下面是一組結果圖: a、沒有異常的try...catch...finally...,且try中或catch中都不含有return                    
b、有異常,但是catch中有return 的try...catch...finally...                     
c、沒有異常,但是try中有return的try...catch...finally...                    
d、有異常,但是catch中沒的return的情況:                  
總結:finally不是必須的,但是隻要有finally,不管有沒有異常finally中的程式碼都必須要執行,其次,如果try中和catch中都不主動跳出程式即都不包含return,那麼不管會不會出現異常,try...catch...finally 塊後面的程式碼都會正常執行,最後,一旦try中的某一行出現異常,就會直接跳到catch中,try中位於這一行後面的程式碼都不會執行。  三、自定義異常類      在程式中,可能會遇到任何標準異常類都沒有能夠充分地描述清楚的問題。在這種情況下,需要建立自己的異常類,這個自己定義的異常類一般都是繼承Exception或者Exception的子類。通常情況下,自己定義的異常類應該有兩個構造器,一個是預設的構造器,另一個是帶有詳細描述資訊的構造器。下面就是定義自己的異常類的兩種方式:
package com.exception;
/*當標準的異常類不能充分的描述清楚問題時,這時需要自定義異常類。
 * 自定義的異常類有兩種方式
 * 一是繼承Exception這個異常主類,或者是繼承Exception這個主類的子類
 * 二是繼承Throwable類
 * */
public class MyException extends Exception{
	private static final long serialVersionUID = 1L;
    public MyException(){
    	super();
    }
    public MyException(String msg){
    	super(msg);
    }
    public MyException(String msg,Throwable cause){
    	super(msg,cause);
    }
    public MyException(Throwable cause){
    	super(cause);
    }
}
//自定義異常類的第二種方式
class MyException_another extends Throwable{
	private static final long serialVersionUID = 1L;
	public MyException_another() {
		super();
	}
	public MyException_another(String msg) {
		super(msg);
	}
	public MyException_another(String msg, Throwable cause) {
		super(msg, cause);
	}
	public MyException_another(Throwable cause) {
		super(cause);
	}
	
}