1. 程式人生 > >異常處理機制

異常處理機制

分享 alt run 指定 ofb stack IV 主動 異常

一、什麽是異常

java的基本理念是“結構不佳的代碼不能運行”,在編譯期間並不能發現所有的錯誤,余下的問題必須在運行階段解決。異常處理是java中唯一正式的錯誤報告機制。異常情形是指阻止當前的方法或者作用域繼續執行的問題。在java中通過異常處理機制來處理程序運行期間出現的錯誤,提升程序的健壯性。

java中與使用其他對象一樣,在堆上創建對象來處理異常。針對不同的異常new出不同的異常對象。異常對象的根類是java.lang.Throwable類。在Java中定義了很多異常類(如OutOfMemoryError、NullPointerException、IndexOutOfBoundsException等),這些異常類分為兩大類:Error和Exception。Error即無法處理的異常,一旦發生終止程序的運行。Exception,是我們可以處理的異常。Exception包括hecked exception和unchecked exception兩類。

unchecked exception(非檢查異常),也稱運行時異常(RuntimeException),比如常見的NullPointerException、IndexOutOfBoundsException。對於運行時異常,java編譯器不要求必須進行異常捕獲處理或者拋出聲明,由程序員自行決定。

checked exception(檢查異常),也稱非運行時異常(運行時異常以外的異常就是非運行時異常),java編譯器強制程序員必須進行捕獲處理,比如常見的IOExeption和SQLException。對於非運行時異常如果不進行捕獲或者拋出聲明處理,編譯都不會通過。

在Java中,異常類的結構層次圖如下圖所示:

技術分享圖片

在Java中,所有異常類的父類是Throwable類,Error類是error類型異常的父類,Exception類是exception類型異常的父類,RuntimeException類是所有運行時異常的父類,RuntimeException以外的並且繼承Exception的類是非運行時異常。常見的異:NullPointerException、IndexOutOfBoundsException、ArrayIndexOutOfBoundsException等等。

異常匹配:拋出異常的時候,異常處理系統會按照代碼的書寫順序找出“最近”的處理程序,找到匹配的處理程序後,則認為異常得到了處理,然後不再繼續查找。查找的時候並不要求拋出的異常同處理程序聲明的異常完全匹配,派生類對象匹配其基類的處理程序。那麽Exception則是所有的異常類的基類,即可捕獲所有的異常。

把“受檢查異常“轉換為“不受檢查的異常”,可以在捕獲到的受檢查異常後,再次拋出一個不受檢查的異常。

二、異常的處理處理方式

1、捕獲

異常的捕獲主要使用try和catch關鍵字,被try塊包圍的代碼,表示這段代碼中可能出現異常,一旦發生異常,異常對象則被cathch捕獲,然後在catch塊中進行處理。如下:

 1 public class Demo5 {
 2     public static void main(String[] args) {
 3         try {
 4             int i=10/0;
 5             System.out.println(i);
 6         } catch (ArithmeticException e) {
 7             e.printStackTrace(System.err);
 8         }
 9     }
10 }
11 輸出的結果:
12 java.lang.ArithmeticException: / by zero
13     at com.sun.lp.demo.Demo5.main(Demo5.java:18)

2、拋出

拋出是異常處理的另外一種方式,顧名思義,一旦發生異常,將異常拋出去,處理的關鍵字是throw和throws,如下:

public class Demo5 {
    public void test() throws Exception{
        try {
            int i = 10/0;
            System.out.println(i);
        } catch (Exception e) {
            //捕獲到異常,不處理,將其拋出
            throw e;
        }
        
    }
    public static void main(String[] args) {
        try {
            Demo5 demo5 = new Demo5();
            demo5.test();
        } catch (Exception e) {
            e.printStackTrace(System.err);
        }
        
        
    }
    
}

結果輸出:

java.lang.ArithmeticException: / by zero
    at com.sun.lp.demo.Demo5.test(Demo5.java:6)
    at com.sun.lp.demo.Demo5.main(Demo5.java:17)

三、自定義異常

不拘泥於java中已有的異常對象,java提供的異常體系不可能預見所有的異常。所以java提供自定義異常的途徑。自定義異常必須從已有異常類的基礎上繼承和拓展。建立新的異常最簡單的方法是讓編譯器為你產生默認的構造器

 1 public class Demo {
 2 
 3     public void test() throws MyException{
 4         System.out.println("Exception is from test()");
 5         throw new MyException();
 6     }
 7     
 8     public static void main(String[] args) {
 9         try {
10             Demo demo = new Demo();
11             demo.test();
12         } catch (Exception e) {
13             System.out.println("get a Exception");
14             e.printStackTrace(System.err);
15         }
16         
17     }
18     
19 }
20 
21 class MyException extends Exception{
22     MyException(){
23         System.out.println("自定義異常類");
24     }
25 }

輸出結果:

Exception is from test()
自定義異常類
get a Exception
com.test.demo.MyException
    at com.test.demo.Demo.test(Demo.java:5)
    at com.test.demo.Demo.main(Demo.java:11)
四、使用finally進行清理
對於一些代碼,無論try塊中的異常是否拋出,它們都能執行,達到這個效果可以使用finally子句。finally子句總能運行。
 1 public class FinallyDemo {
 2     public static int count=0;
 3     public static void main(String[] args) {
 4         while(true){
 5             try {
 6                 if(count++==0)
 7                     throw new SimpleException();
 8                 System.out.println("No Exception");
 9             } catch (SimpleException e) {
10                 System.out.println("get a SimpleException");
11             }finally{
12                 System.out.println("finally 子句執行");
13                 if(count==2) break;
14             }
15         }
16     }
17 }
18 class SimpleException extends Exception{
19     SimpleException(){
20         super();
21     }
22 }

輸出結果:

get a SimpleException
finally 子句執行
No Exception
finally 子句執行

五、幾個關鍵字的使用

1.try關鍵字用來包圍可能會出現異常的邏輯代碼,它單獨無法使用,必須配合catch或者finally使用。三個塊執行的順序為try—>catch—>finally。Java編譯器允許的組合使用形式只有以下三種形式:

try...catch...; try....finally......; try....catch...finally...

2.throws和thow關鍵字

throws出現在方法的聲明中,表示該方法可能會拋出的異常,然後交給上層調用它的方法程序處理,允許throws後面跟著多個異常類型。

throw一般用於程序出現某種邏輯,程序員主動拋出指定的異常對象,throw主要出現在方法體中,拋出的異常對象可以進行向上轉型。

3.由於垃圾回收機制的存在,finally主要是把除內存資源之外的資源恢復到它們的初始狀態,例如:關閉文件流,網絡聯機,關閉數據庫連接等等。

六、異常使用指南

1)在恰當的級別處理問題(在知道如何處理的情況下才捕獲異常)

2)解決問題並重新調用產生異常的方法

3)進行少許的修補,然後繞過異常發生的地方繼續執行

4)用別的數據進行計算,以代替方法預計會返回的值

5)把當前運行環境下能做的事情盡量做完,然後把相同的異常拋出到更高層

6)把當前運行環境下能做的事情盡量做完,然後把不相同的異常拋出到更高層

7)終止程序

8)進行簡化

9)讓類庫和程序更安全。

異常處理機制