Java 異常體系(美團面試)


 Java把異常作為一種類,當做對象來處理。所有異常類的基類是Throwable類,兩大子類分別是Error和Exception。

  系統錯誤由Java虛擬機拋出,用Error類表示。Error類描述的是內部系統錯誤,例如Java虛擬機崩潰。這種情況僅憑程序自身是無法處理的,在程序中也不會對Error異常進行捕捉和拋出。

  異常(Exception)又分為RuntimeException(運行時異常)和CheckedException(檢查時異常),兩者區別如下:

  • RuntimeException:程序運行過程中才可能發生的異常。一般為代碼的邏輯錯誤。例如:類型錯誤轉換,數組下標訪問越界,空指針異常、找不到指定類等等。
  • CheckedException:編譯期間可以檢查到的異常,必須顯式的進行處理(捕獲或者拋出到上一層)。例如:IOException, FileNotFoundException等等。

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

1、簡單的:

2、復雜的:

 

首先說明一點,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異常,一般情況下不自定義檢查異常。

2. 異常的處理

  常用關鍵字:try、catch、throw(拋出一個異常,動詞)、throws(聲明一個方法可能拋出的異常)finally。

2.1 throws 聲明異常

  若方法中存在檢查時異常,如果不對其捕獲,那必須在方法頭中顯式聲明該異常,以便於告知方法調用者此方法有異常,需要進行處理。 

  在方法中聲明一個異常,方法頭中使用關鍵字throws,后面接上要聲明的異常。若聲明多個異常,則使用逗號分割。

  若是父類的方法沒有聲明異常,則子類繼承方法后,也不能聲明異常。

2.2  try-catch(捕獲異常)

  若執行try塊的過程中沒有發生異常,則跳過catch子句。若是出現異常,try塊中剩余語句不再執行。開始逐步檢查catch塊,判斷catch塊的異常類實例是否是捕獲的異常類型。匹配后執行相應的catch塊中的代碼。如果異常沒有在當前的方法中被捕獲,就會被傳遞給該方法的調用者。這個過程一直重復,直到異常被捕獲或被傳給main方法(交給JVM來捕獲)。

  對於try..catch捕獲異常的形式來說,對於異常的捕獲,可以有多個catch。對於try里面發生的異常,他會根據發生的異常和catch里面的進行匹配(按照catch塊從上往下匹配),如果有匹配的catch,它就會忽略掉這個catch后面所有的catch。

  如果有finally的話進入到finally里面繼續執行。

  try  ctach  fianally 中有return 時,會先執行return ,但是不會返回。在執行完 finally 后 進行返回。

  return 的是基本類型數據時, fianlly 里面的語句不會影響 return 的值,

  return 的是引用類型數據時,此時已經確定了要返回對象的地址(地址一),后面 fianlly 里面的可以通過修改前面地址一中的內容修改返回的內容,

  但是如果將對象指向另一個地址(地址二),則不會影響返回的內容。因為返回的對象地址已經確定為地址一,只能通過修改地址一對象的內容修改返回的信息。 

二異常的捕獲和處理

異常處理的步驟:

throw  try catch finally throws下面是在網絡通信中運用socket的一段代碼: 

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關鍵字用法如下: 

public static void test() throws Exception  
{  
   throw new Exception("方法test中的Exception");  
}  

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

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

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。

參考:Java 異常體系

參考:java異常體系結構詳解

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM