1. 程式人生 > >Java 異常結構體系

Java 異常結構體系

前幾天在參加網易和360公司的線上考試的時候,都出了一道關於java中異常類的多項選擇題。這幾天翻看了相關書籍和網上一些資料,結合自己的理解與思考,將自己的一些收穫記錄如下:

先來看看java中異常的體系結構圖解:


首先說明一點,java中的Exception類的子類不僅僅只是像上圖所示只包含IOException和RuntimeException這兩大類,事實上Exception的子類很多很多,主要可概括為:執行時異常與非執行時異常。

一java異常體系結構

從上述圖示可以看到,

 Thorwable類(表示可丟擲)是所有異常和錯誤的超類,兩個直接子類為Error和Exception,分別表示錯誤和異常。其中異常類Exception又分為執行時異常(RuntimeException)和非執行時異常,  這兩種異常有很大的區別,也稱之為不檢查異常(Unchecked Exception)和檢查異常(Checked Exception)。下面將詳細講述這些異常之間的區別與聯絡:

1、Error與Exception
    Error是程式無法處理的錯誤,它是由JVM產生和丟擲的,比如OutOfMemoryError、ThreadDeath等。這些異常發生時,Java虛擬機器(JVM)一般會選擇執行緒終止。
    Exception是程式本身可以處理的異常,這種異常分兩大類執行時異常和非執行時異常。程式中應當儘可能去處理這些異常。
2、執行時異常和非執行時異常
    執行時異常都是RuntimeException類及其子類異常,如NullPointerException、IndexOutOfBoundsException等,這些異常是不檢查異常,程式中可以選擇捕獲處理,也可以不處理。這些異常一般是由程式邏輯錯誤引起的,程式應該從邏輯角度儘可能避免這類異常的發生。
    非執行時異常是RuntimeException以外的異常,型別上都屬於Exception類及其子類。從程式語法角度講是必須進行處理的異常,如果不處理,程式就不能編譯通過。如IOException、SQLException等以及使用者自定義的Exception異常,一般情況下不自定義檢查異常。

二異常的捕獲和處理

異常處理的步驟:

throw  try catch finally throws下面是在網路通訊中運用socket的一段程式碼:

[java] view plaincopyprint?
  1. <span style=“white-space:pre”>                    </span>try {  
  2.                         mSocket=new Socket(ip,port);  
  3.                         if(mSocket!=null)  
  4.                         {  
  5.                             Log.i(”Client”,“socket is create”);  
  6.                             clientInput=new ClientInputThread(mSocket);  
  7.                             clientOutput=new ClientOutputThread(mSocket);  
  8.                             clientInput.setStart(true);  
  9.                             clientOutput.setStart(true);  
  10.                             clientInput.start();  
  11.                             clientOutput.start();  
  12.                         }  
  13.                         else {  
  14.                             Log.i(”Client”,“socket is not create”);  
  15.                         //  Toast.makeText(, ”親,伺服器端連接出錯”,0).show();
  16.                         }  
  17.                     } catch (UnknownHostException e) {  
  18.                         // TODO Auto-generated catch block
  19.                         e.printStackTrace();  
  20.                     } catch (IOException e) {  
  21.                         // TODO Auto-generated catch block
  22.                         e.printStackTrace();  
  23.                     }finally{}  
<span style="white-space:pre">                    </span>try {
                        mSocket=new Socket(ip,port);
                        if(mSocket!=null)
                        {
                            Log.i("Client","socket is create");
                            clientInput=new ClientInputThread(mSocket);
                            clientOutput=new ClientOutputThread(mSocket);
                            clientInput.setStart(true);
                            clientOutput.setStart(true);

                            clientInput.start();
                            clientOutput.start();

                        }
                        else {
                            Log.i("Client","socket is not create");
                        //  Toast.makeText(, "親,伺服器端連接出錯",0).show();
                        }
                    } catch (UnknownHostException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();

                    }finally{}

從上述程式碼可以看到異常處理的步驟為


2、 try、catch、finally三個語句塊應注意的問題
    第一:try、catch、finally三個語句塊均不能單獨使用,三者可以組成 try…catch…finally、try…catch、try…finally三種結構,catch語句可以有一個或多個,finally語句最多一個。
    第二:try、catch、finally三個程式碼塊中變數的作用域為程式碼塊內部,分別獨立而不能相互訪問。如果要在三個塊中都可以訪問,則需要將變數定義到這些塊的外面。
    第三:多個catch塊時候,最多隻會匹配其中一個異常類且只會執行該catch塊程式碼,而不會再執行其它的catch塊,且匹配catch語句的順序為從上到下,也可能所有的catch都沒執行。
      第四:先Catch子類異常再Catch父類異常。
用示意圖表示如下:



3、throw、throws關鍵字
    throw關鍵字是用於方法體內部,用來丟擲一個Throwable型別的異常。如果丟擲了檢查異常,則還應該在方法頭部宣告方法可能丟擲的異常型別。該方法的呼叫者也必須檢查處理丟擲的異常。如果所有方法都層層上拋獲取的異常,最終JVM會進行處理,處理也很簡單,就是列印異常訊息和堆疊資訊。throw關鍵字用法如下:

[java] view plaincopyprint?
  1. publicstaticvoid test() throws Exception  
  2. {  
  3.    thrownew Exception(“方法test中的Exception”);  
  4. }  
public static void test() throws Exception
{
   throw new Exception("方法test中的Exception");
}

  throws關鍵字用於方法體外部的方法宣告部分,用來宣告方法可能會丟擲某些異常。僅當丟擲了檢查異常,該方法的呼叫者才必須處理或者重新丟擲該異常。當方法的呼叫者無力處理該異常的時候,應該繼續丟擲.



注意一個方法throws出某個異常但是該方法內部可以不throw出該異常,程式碼如下:

[java] view plaincopyprint?
  1. class ER extends RuntimeException  
  2. {  
  3. }  
  4. class SomeClass  
  5. {  
  6.     publicvoid fun()throws ER  
  7.     {  
  8.         System.out.println(”AAAA”);  
  9.     }  
  10. }  
  11. publicclass ExceptionTest {  
  12.     publicstaticvoid main(String[] args) {  
  13.         // TODO Auto-generated method stub
  14.         SomeClass A=new SomeClass();  
  15.         A.fun();  
  16.     }  
  17. }  
class ER extends RuntimeException
{

}
class SomeClass
{
    public void fun()throws ER
    {
        System.out.println("AAAA");

    }
}

public class ExceptionTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        SomeClass A=new SomeClass();
        A.fun();
    }
}
程式執行結果如下:AAAA。