簡體   English   中英

運行時/已檢查/未檢查/錯誤/異常之間的差異

[英]Differences between Runtime/Checked/Unchecked/Error/Exception

什么是運行時異常,什么是已檢查/未檢查異常以及錯誤/異常之間的區別。為什么有這么多類型? 相反,Java 可能只是遵循一個簡單的設計(只是嘗試/捕獲所有類型)來處理程序中的異常情況?

由於我是一個新的Java開發人員,在區分和處理不同類型的異常方面也遇到了一些困難。 這就是為什么我在這個主題上做了一個簡短的筆記,每當我感到困惑時,我都會仔細閱讀。 這是Throwable類層次結構的圖像:
Throwable 類層次結構

[圖像由JavaTpoint 提供]。

這里需要記住三個關鍵類: ThrowableExceptionError 在這些類中, Exception可以分為兩類:“Checked Exception”和“Unchecked Exception”。

檢查異常:

  • 這些是擴展Throwable的類,除了RuntimeExceptionError
  • 它們也被稱為編譯時異常,因為它們在編譯時被檢查,這意味着編譯器強制我們要么用try/catch處理它們,要么在函數簽名中指出它throws它們並迫使我們在調用者中處理它們。
  • 它們是由代碼控制之外的意外情況(例如數據庫關閉、文件 I/O 錯誤、錯誤輸入等)引起的可通過編程方式恢復的問題。
  • 示例: IOExceptionSQLException等。

未經檢查的異常:

  • 擴展RuntimeException的類稱為未經檢查的異常。
  • 未經檢查的異常不在編譯時檢查,而是在運行時檢查,因此得名。
  • 它們也是可通過編程方式恢復的問題,但與檢查異常不同,它們是由代碼流或配置中的錯誤引起的。
  • 示例: ArithmeticExceptionNullPointerExceptionArrayIndexOutOfBoundsException等。
  • 由於它們是編程錯誤,因此可以通過良好/明智的編碼來避免它們。 例如,“除以零”會產生ArithmeticException ,這可以通過對除數進行簡單檢查來避免。 同樣,我們可以通過簡單地檢查引用來避免NullPointerExceptionif (object != null)或者甚至使用更好的技術

錯誤:

  • Error是指無法由try/catch處理的不可恢復情況。
  • 示例: OutOfMemoryErrorVirtualMachineErrorAssertionError等。

為什么有這么多類型?

除了Stephen C的回答我想說:異常處理是 Java 中相對昂貴的操作。 我們不應該將所有異常情況都放在try/catch塊中。 過度使用try/catch可能會影響程序性能。

總之,應盡可能以編程方式處理Exception 另一方面,我們無法處理Error ,所以這些可能是存在多種異常類型的一些合乎邏輯的原因。

Throwable 位於所有異常的頂部。 在 Throwable 下面你有錯誤和異常。 在異常下面你有運行時異常。

Java 有兩種類型的異常 - 已檢查和未檢查。 檢查異常由編譯器強制執行(您必須在 throws 子句中聲明它們並最終捕獲它們)。 在 throws 子句中捕獲或聲明不強制執行未經檢查的異常。

(答案中有爭議的部分)

Throwable 存在,因此所有異常類型都有一個父級。 你永遠不應該聲明你拋出 Throwable 並且永遠不會抓住它(除非你真的真的很清楚自己在做什么)。

存在錯誤以指示運行時環境問題,您的程序可能無法從中恢復的問題,例如格式錯誤的類文件或 VM 內存不足。 除非您真的知道自己在做什么,否則您不應該捕獲錯誤。

異常作為所有非程序員錯誤的根存在(有關此“異常”的信息,請參閱 RuntimeException),例如由於磁盤已滿而無法創建文件。 您不應該拋出、拋出或捕獲異常。 如果您必須捕獲異常,請確保您知道自己在做什么。

RuntimeException 存在以指示所有程序員錯誤,例如越過數組的末尾或調用空對象上的方法。 這些是你應該修復的東西,這樣它們就不會拋出異常——這表明你,程序員,搞砸了代碼。 同樣,除非你知道自己在做什么,否則你不應該抓住這些。

TofuBeer 的回答清楚地解釋了異常類的含義。

為什么有這么多類型? 相反,Java 可能只是遵循一個簡單的設計(只是嘗試/捕獲所有類型)來處理程序中的異常情況?

為什么? 因為它們是必需的! 如果沒有這 4 個類,按大類處理異常將是不切實際的。

  • 如果沒有Error類,您將如何捕獲“所有致命的 JVM 錯誤”?
  • 如果沒有Exception類,您將如何捕獲“所有非 JVM 致命錯誤的Exception
  • 如果沒有RuntimeException類,您將如何捕獲“所有未經檢查的異常”?
  • 錯誤(由 VM 拋出,不應被捕獲或處理)
    1. 虛擬機錯誤
    2. 斷言錯誤
    3. 鏈接錯誤...等等
  • 運行時/取消檢查異常(編程錯誤,不應被捕獲或處理)
    1. 空指針異常
    2. ArrayIndexOutOfBoundException
    3. IllegalArgumentException ... 等等
  • 檢查異常(任何其他,應用程序應被捕獲或處理)
    1. IO異常
    2. 文件未找到異常
    3. SQLException ...等等

Checked 和 unchecked 異常的區別:

我們在檢查異常和未檢查異常之間有很多區別,但所有的區別都源於一個基本的考慮,即異常是否可以被編譯器解決。

要記住的要點是:

[1] 檢查異常表示編譯器檢查異常 這意味着編譯器要求此類異常由 try-catch 塊或 throws 關鍵字處理。

[2] 未經檢查的異常是編譯器沒有提供任何授權的異常,因為它們可以由開發人員通過編碼/編程來解決,因為控制流是可控的,如 ArithmeticException、NullPointerException ArrayIndexOutOfBoundsException、IllegalArgumentException 等。

我稱之為“異常身份測試” ,您可以從 java doc 中獲取任何隨機異常,然后只問一個問題。 “嘿例外! 能用程序解決嗎?”

如果異常為YES,則它是未檢查的異常,因為這可以通過更改代碼或解決某些計算錯誤等來解決。

另一方面,如果異常表示否,那么這就是檢查異常,因為在檢查異常控制流程中,如果有人更改了數據庫密碼或有人拔掉了網線,連接超時(ConnectException),某些資源未找到( FileNotFoundException, ClassNotFound), SQLException, InvocatonTargetException 等,這些是編程無法解決的

本文以清晰簡潔的方式總結了已檢查未檢查的異常。

  • Checked ExceptionsChecked Exceptions是可以在編譯時檢測、識別和檢查的異常。 如果代碼塊拋出已檢查的異常,則該方法必須處理該異常或必須使用throws關鍵字指定異常。

    • 示例

       public void testDB() throws ClassNotFoundException, SQLException { Class.forName("com.mysql.jdbc.Driver"); System.out.println("Driver Loaded"); Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/selenium","root","root"); System.out.println("Connected to MySQL DB"); }
    • 我們要么需要使用 throws 指定異常列表,要么需要使用try-catch{}塊。 我已經在下面的程序中演示了throws的用法。

  • Unchecked Exceptions : Unchecked Exceptions在編譯時不被檢查。 ErrorRuntimeException類下的 Java 異常是未經檢查的異常,而throwable下的所有其他異常都經過檢查。

摘要:如果可以合理地期望客戶端從異常中恢復,請將其設置為已檢查異常。 如果客戶端無法從異常中恢復,請將其設為未經檢查的異常。

下圖顯示了Exception類的層次結構。 所有Exception對象的基類都是java.lang.Throwable ,以及它的兩個子類java.lang.Exceptionjava.lang.Error

在此輸入圖像描述

  • Error類描述了很少發生的內部系統錯誤(例如, VirtualMachineErrorLinkageError )。 如果發生此類錯誤,您幾乎無法執行該操作,Java運行時將終止該程序。

  • Exception類描述了程序引起的錯誤(例如FileNotFoundExceptionIOException )。 這些錯誤可以由您的程序捕獲和處理(例如,執行備用操作或通過關閉所有文件,網絡和數據庫連接來執行正常退出)。

Checked vs Unchecked

如圖所示, ErrorRuntimeException的子類稱為未經檢查的異常。 編譯器不會檢查這些異常,因此不需要捕獲或聲明在程序中拋出這些異常。 這是因為您可以對這些異常做很多事情。 例如,“除以0”觸發ArithmeticException ,數組索引超出綁定觸發ArrayIndexOutOfBoundException ,它們實際上是編譯邏輯錯誤,應該在編譯時修復,而不是將其留給運行時異常處理。

所有其他異常都稱為檢查異常。 它們由編譯器檢查,必須被捕獲或聲明被拋出。

編譯器不檢查RuntimeException及其子類,也不需要在方法的簽名中聲明。 因此,請謹慎使用它們,因為您不會被告知並且可能不會意識到使用該方法可能發生的異常(因此沒有正確的異常處理代碼) - 一種糟糕的軟件工程實踐。

來源就在這里

運行時異常為您提供了避免捕獲和聲明異常的靈活性。

Exceptions are two types in java:

1. **Checked Exception: The exceptions which are checked by compiler. 

例如:我們正在對文件進行操作,那么編譯器會要求您通過 try-catch 塊或 throws 關鍵字來處理 IOException。

2. Unchecked Exception: The exceptions which are not checked by compiler at run time. 

例如:如果您正在對一個對象進行操作而不創建它; 在這種情況下,您將得到 NullPointerException。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM