天天看點

java中的異常處理

一:異常的概念:

  Java把異常當作對象來處理,并定義一個基類java.lang.Throwable作為所有異常的超類。

 在Java API中已經定義了許多異常類,這些異常類分為兩大類,錯誤Error和異常Exception。

我們先檢視一下異常類的樹狀體系結構,如下:

java中的異常處理

Thorwable類所有異常和錯誤的超類,有兩個子類Error和Exception,分别表示錯誤和異常。其中異常類Exception又分為運作時異常(RuntimeException)和非運作時異常, 這兩種異常有很大的差別,也稱之為不檢查異常(Unchecked Exception) 和檢查異常(Checked Exception)。

1:Error和Exception

Error是程式無法處理的錯誤,比如OutOfMemoryError、ThreadDeath等。這些異常發生時,  Java虛拟機(JVM)一般會選擇線程終止。

Exception是程式本身可以處理的異常,這種異常分兩大類運作時異常(不可查異常)和非運作時異常(可查異常)。 程式中應當盡可能去處理這些異常。

2:運作時異常和非運作時異常

 運作時異常都是RuntimeException類及其子類異常,如NullPointerException、IndexOutOfBoundsException等, 這些異常是不檢查異常,程式中可以選擇捕獲處理,也可以不處理。這些異常一般是由程式邏輯錯誤引起的, 程式應該從邏輯角度盡可能避免這類異常的發生。

這類異常程式不要求必須去做處理。

非運作時異常是RuntimeException以外的異常,類型上都屬于Exception類及其子類。 從程式文法角度講是必須進行處理的異常,如果不處理,程式就不能編譯通過。 如IOException、SQLException等以及使用者自定義的Exception異常,一般情況下不自定義檢查異常。

這類異常則要求我們對這個異常進行處理,要麼使用try--catch--finally,要麼使用throws去聲明這個異常。

二:異常的處理:

 首先在java中,都是通過 try--catch--finally,throw,throws關鍵字進行的。

1:異常處理的基本文法:

try--catch--finally:

1 package Enum;
 2 
 3 public  class MyClass{
 4     public static void main(String[] args) {
 5         try {
 6             //可能會出現異常的代碼塊
 7         } catch (Exception e) {//想要捕獲的異常
 8             //異常的處理
 9             e.printStackTrace();
10         }finally{
11             //不管怎樣都會被運作的語句,例如關閉連結資源,關閉連接配接對象
12         }
13     }
14 }      

1: try語句塊,表示要嘗試運作代碼,try語句塊中代碼受異常監控,其中代碼發生異常時,會抛出異常對象。 

catch語句塊會捕獲try代碼塊中發生的異常并在其代碼塊中做異常處理,catch語句帶一個Throwable類型的參數, 表示可捕獲異常類型。當try中出現異常時,catch會捕獲到發生的異常,并和自己的異常類型比對, 若比對,則執行catch塊中代碼,并将catch塊參數指向所抛的異常對象。catch語句可以有多個,  用來比對多個中的一個異常,一旦比對上後,就不再嘗試比對别的catch塊了,是以如果需要比對多個異常就把異常的子類放到前面,父類放到後面。 通過異常對象可以擷取異常發生時完整的JVM堆棧資訊,以及異常資訊和異常發生的原因等。

 finally語句塊是緊跟catch語句後的語句塊,這個語句塊總是會在方法傳回前執行,  而不管是否try語句塊是否發生異常。并且這個語句塊總是在方法傳回前執行。 目的是給程式一個補救的機會。這樣做也展現了Java語言的健壯性。

2、 try、catch、finally三個語句塊應注意的問題 :

    第一、try、catch、finally三個語句塊均不能單獨使用,三者可以組成 try...catch...finally、try...catch、

    try...finally三種結構,catch語句可以有一個或多個,finally語句最多一個。

    第二、try、catch、finally三個代碼塊中變量的作用域為代碼塊内部,分别獨立而不能互相通路。

    如果要在三個塊中都可以通路,則需要将變量定義到這些塊的外面。

    第三、多個catch塊時候,隻會比對其中一個異常類并執行catch塊代碼,而不會再執行别的catch塊,

    并且比對catch語句的順序是由上到下。

throw、throws關鍵字

 throw關鍵字是用于方法體内部,用來抛出一個Throwable類型的異常。如果抛出了檢查異常, 則還應該在方法頭部聲明方法可能抛出的異常類型。該方法的調用者也必須檢查處理抛出的異常。 如果所有方法都層層上抛擷取的異常,最終JVM會進行處理,處理也很簡單,就是列印異常消息和堆棧資訊。 如果抛出的是Error或RuntimeException,則該方法的調用者可選擇處理該異常。有關異常的轉譯會在下面說明。

throws關鍵字用于方法體外部的方法聲明部分,用來聲明方法可能會抛出某些異常。僅當抛出了檢查異常, 該方法的調用者才必須處理或者重新抛出該異常。當方法的調用者無力處理該異常的時候,應該繼續抛出。

 例如throws申明一個異常:

 1 public void test() throws ClassNotFoundException{

3 } 

 例如這個throw 觀察一下有什麼不同:

1 public void test() throws ClassNotFoundException {
 2     throw new ClassNotFoundException();
 3     
 4     }
 5 
 6 
 7 
 8 
 9 
10 public void test() {
11         throw new RuntimeException();
12     
13     }      

這很好的說明了 throw對與可查異常和不可查異常處理之間的差别

 Throwable類中的常用方法

      getCause():傳回抛出異常的原因。如果 cause 不存在或未知,則傳回 null。

      getMessage():傳回異常的消息資訊。

      printStackTrace():對象的堆棧跟蹤輸出至錯誤輸出流,作為字段 System.err 的值。

1 public  class MyClass{
 2     public static void main(String[] args) {
 3         
 4         try {
 5             
 6         } catch (Exception e) {
 7             // TODO: handle exception
 8             e.printStackTrace();
 9             e.getMessage();
10             e.getCause();
11             
12         }
13     }
14           

 三:異常的一般原則:

 1、 能處理就早處理,抛出不去還不能處理的就想法消化掉或者轉換為RuntimeException處理。

    因為對于一個應用系統來說,抛出大量異常是有問題的,應該從程式開發角度盡可能的控制異常發生的可能。

 2、 對于檢查異常,如果不能行之有效的處理,還不如轉換為RuntimeException抛出。

    這樣也讓上層的代碼有選擇的餘地――可處理也可不處理。

 3、 對于一個應用系統來說,應該有自己的一套異常處理架構,這樣當異常發生時,也能得到統一的處理風格,

    将優雅的異常資訊回報給使用者。

  四:自定義異常:

 首先 建立一個類繼承異常類,代碼如下:

1 package Exection;
 2 
 3 public class Myexecption extends Exception{
 4 
 5     public Myexecption() {
 6         super();
 7         // TODO Auto-generated constructor stub
 8     }
 9 
10     public Myexecption(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
11         super(message, cause, enableSuppression, writableStackTrace);
12         // TODO Auto-generated constructor stub
13     }
14 
15     public Myexecption(String message, Throwable cause) {
16         super(message, cause);
17         // TODO Auto-generated constructor stub
18     }
19 
20     public Myexecption(String message) {
21         super(message);
22         // TODO Auto-generated constructor stub
23     }
24 
25     public Myexecption(Throwable cause) {
26         super(cause);
27         // TODO Auto-generated constructor stub
28     }
29     
30 }      

 然後編寫代碼 ,然後編寫邏輯,這個異常什麼時候需要使用,

1 package Exection;
 2 
 3 public class Test {
 4     public static  int shang (int x,int y) throws Myexecption{
 5          if(y==0)  
 6             {  
 7                 throw new Myexecption("您輸入的是"+y+",規定除數不能為0!");//抛出異常  
 8             }  
 9         return x/y;
10     }
11     
12     public static void main(String[] args) throws Myexecption {
13         shang(10, 0);
14     }
15 }      

 在需要的地方抛出這個異常。

運作結果如下:

java中的異常處理

好了  異常就到這了;

歡迎大家一起說出自己的想法。