天天看點

Error 與 Exception 差別Error 與 Exception 差別

文章目錄

  • Error 與 Exception 差別
    • Error
    • Exception
    • 常見面試題
    • 參考

Error 與 Exception 差別

Exception 和 Error 都是繼承了 Throwable 類,在 Java中 隻有 Throwable 類型的執行個體才可以被抛出(throw)或者捕獲(catch),它是異常處理機制的基本組成類型。

Error 與 Exception 差別Error 與 Exception 差別

Error

Error 是指在正常情況下,不大可能出現的情況,絕大部分的 Error 都會導緻程式(比如JVM自身)處于非正常的、不可恢複狀态。既然是非正常情況,是以不便于也不需要捕獲,常見的比如

OutOfMemoryError

之類,都是 Error 的子類。

Exception

Exception 是程式正常運作中,可以預料的意外情況,可能并且應該被捕獲,進行相應處理。Exception 又分為檢查(checked)異常、非檢查(unchecked)異常,檢查異常在源代碼裡必須顯式地進行捕獲處理,這是編譯期檢查的一部分。非檢查異常就是所謂的運作時異常,類似

NullPointerException

ArrayIndexOutOfBoundsException

之類,通常是可以編碼避免的邏輯錯誤,具體根據需要來判斷是否需要捕獲,并不會在編譯期強制要求。

RuntimeException

類的子類屬于非檢查異常,除此之外繼承自 Exception 的類為檢查異常。

  • 通過 throws 關鍵字聲明抛出異常
private static void readFile(String filePath) throws IOException {
        File file = new File(filePath);
        String result;
        BufferedReader reader = new BufferedReader(new FileReader(file));
        while ((result = reader.readLine()) != null) {
            System.out.println(result);
        }
        reader.close();
    }
           
  • try-catch 處理異常
private static void readFile(String filePath) {
        File file = new File(filePath);
        String result;
        BufferedReader reader;
        try {
            reader = new BufferedReader(new FileReader(file));
            while ((result = reader.readLine()) != null) {
                System.out.println(result);
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
           

常見面試題

  1. Error 和 Exception 差別是什麼?

Error

錯誤通常為虛拟機相關錯誤,如系統崩潰,記憶體不足,堆棧溢出等,編譯器不會對這類錯誤進行檢測,JAVA 應用程式也不應對這類錯誤進行捕獲,一旦這類錯誤發生,通常應用程式會被終止,僅靠應用程式本身無法恢複。

Exception

異常是可以在應用程式中進行捕獲并處理的,通常遇到這種錯誤,應對其進行處理,使應用程式可以繼續正常運作。

  1. 運作時異常和一般異常差別是什麼?

編譯器不會對運作時異常進行檢測,沒有 try-catch,方法簽名中也沒有 throws 關鍵字聲明,編譯依然可以通過。如果出現了 RuntimeException, 那一定是程式員的錯誤。

一般異常如果沒有 try-catch,且方法簽名中也沒有用 throws 關鍵字聲明可能抛出的異常,則編譯無法通過。這類異常通常為應用環境中的錯誤,即外部錯誤,非應用程式本身錯誤,如檔案找不到等。

  1. NoClassDefFoundError 和 ClassNotFoundException 差別?

NoClassDefFoundError

是一個 Error 錯誤,産生原因:如果 JVM 或者 ClassLoader 執行個體嘗試加載類的時候找不到類的定義。要查找的類在編譯的時候是存在的,運作的時候卻找不到了,就會導緻 NoClassDefFoundError。造成該問題的原因可能是打包過程漏掉了部分類,或者 jar 包出現損壞或者篡改。解決辦法是查找那些在開發期間存在于類路徑下但在運作期間卻不在類路徑下的類。

ClassNOtFoundException

是一個 Exception 屬于檢查異常,産生原因:Java 支援使用 Class.forName 方法來動态地加載類,任意一個類的類名如果被作為參數傳遞給這個方法都将導緻該類被加載到 JVM 記憶體中,如果這個類在類路徑中沒有被找到,就會在運作時抛出 ClassNotFoundException 異常。解決該問題需要確定所需的類連同它依賴的包存在于類路徑中,常見問題在于類名書寫錯誤。另外還有一個原因就是:當一個類已經由某個類加載器加載到記憶體中了,此時另一個類加載器又嘗試着動态地從同一個包中加載這個類。通過控制動态類加載過程,可以避免上述情況發生。

  1. JVM 是如何處理異常的?

在一個方法中如果發生異常,這個方法會建立一個異常對象,并轉交給 JVM,該異常對象包含異常名稱,異常描述以及異常發生時應用程式的狀态。建立異常對象并轉交給 JVM 的過程稱為抛出異常。可能有一系列的方法調用,最終才進入抛出異常的方法,這一系列方法調用的有序清單叫做調用棧。

JVM 會順着調用棧去查找看是否有可以處理異常的代碼,如果有,則調用異常處理代碼。當 JVM 發現可以處理異常的代碼時,會把發生的異常傳遞給它。如果 JVM 沒有找到可以處理該異常的代碼塊,JVM 就會将該異常轉交給預設的異常處理器(預設處理器為 JVM 的一部分),預設異常處理器列印出異常資訊并終止應用程式。

  1. throw 和 throws 的差別是什麼?

throw

關鍵字用來抛出方法或代碼塊中的異常,檢查異常和非檢查異常都可以被抛出。

throws

關鍵字用在方法簽名處,用來辨別該方法可能抛出的異常清單。一個方法用 throws 辨別了可能抛出的異常清單,調用該方法的方法中必須包含可處理異常的代碼,否則也要在方法簽名中用 throws 關鍵字聲明相應的異常。

  1. 常見的 RuntimeException 有哪些?
  • ClassCastException

    (類轉換異常)
  • IndexOutOfBoundsException

    (數組越界)
  • NullPointerException

    (空指針異常)

參考

[1] 極客時間:楊曉峰-java核心技術36講

[2] 一文讀懂 JAVA 異常處理