淺談Java中的異常種類

前言

一般來講,關於報錯信息主要分爲兩大類,即Exception(異常)Error(錯誤),有時候我們用“異常”來統稱這兩種情況,在本文中,將會就這兩種情況做進一步的講解

同時,在這裏我先聲明,本文將不含Java對異常的處理方式、各個異常的詳細講解以及編譯後代碼中異常處理的講解,而僅僅是針對Java中各種異常大類做一個粗略的討論

概念

我們一般將宏觀概念的異常分爲以下兩類,它們都屬於Java中Throwable的子類:

  • Error
  • Exception

而Exception又可以進一步劃分爲以下這些種類:

  • 受檢異常/編譯期異常
  • 非受檢異常/運行時異常

關於這些概念都是什麼意思,接下來就會馬上來進行進一步的講解

Error

Error一般是程序中較嚴重的出錯,是虛擬機層面的異常,一旦發生將會導致系統崩潰,無法由程序自身處理,通常有以下兩種情況:

  • OutOfMemoryError:又稱OOM,表示內存溢出錯誤,通常發生在內存泄露或內存不足的情況
  • StackOverflowError:表示棧溢出錯誤,通常發生在遞歸過深的情況

這兩種異常一個通常發生在Java堆上,一個通常發生在虛擬機棧上,看到共同點了嗎?沒錯,就是Error通常和JVM的內存區域脫不開關係,一旦程序報了Error,那我們一般都會去查看heap dump文件、修改JVM參數等一系列底層措施,而且一旦發生了Error,程序是會直接崩潰的,不能採取任何Java代碼層面的措施來彌補

Exception

Exception相比於Error就不那麼嚴重,但是發生的次數卻相當頻繁,不過Java爲我們提供了try-catch系列語法來捕獲這些異常。既然是捕獲,那相比於Error發生只能眼睜睜看着系統崩潰,Exception我們可以進行手動的捕獲操作,當異常發生時,進行一些處理操作,來儘可能減少其危害

Exception相比於Error來講,種類極爲繁多,所以我們將Exception按照特性,分爲受檢異常非受檢異常,接下來我們就會針對這兩種情況再單獨討論

受檢異常/編譯期異常

受檢異常,也叫編譯期異常,一般我們指需要在代碼中顯式處理的異常,如今的編譯器會強制提示你進行try-catch的捕獲,同時Java也強制約束你進行捕獲操作,否則就會在編譯階段報錯,這也是編譯期異常名字的由來

這類異常也可以再進一步劃分,這裏參考阿里公司出版的《碼出高效:Java開發手冊》,將受檢異常進一步劃分爲以下兩類:

  • 不可處理異常:程序無法自行處理的異常,進行任何試圖解決異常的行爲都是於事無補的,最常見的處理方式是完整保存現場狀態,供之後分析解決
  • 可處理異常:程序可以進行一些設置好的操作來盡最大程度降低異常的影響,這些異常中很大一部分是我們預計會發生的,屬於程序執行流的一環

不可處理異常中,常見的有SQLException、ClassNotFoundException等,這些異常發生時,無論怎麼重試,怎麼處理都是於事無補的,只能回頭檢查程序

這類錯誤一般都是代碼編寫錯誤或者配置文件配置項錯誤,Java程序是不可能幫你手動更改的,但是由於這種異常發生後會導致一系列連鎖反應,所以Java語言會強制你捕獲這類異常,這類異常的捕獲並不是爲了進行處理,而是爲了讓程序提前終止,來讓你儘早排查錯誤

可處理異常中,最常見的就是各種安全框架中的未認證異常和登陸失敗異常,這類異常通常屬於我們規劃好的執行流圖中的一環,我們也早就準備好了發生異常時的處理措施,比如進行頁面跳轉之類

這類錯誤一般是由於一些外部因素,且這些外部因素髮生概率非常高,所以Java語言強制需要你進行捕獲,這類異常的捕獲通常是爲了讓程序能夠繼續執行,或者安全正常的結束

非受檢異常/運行時異常

非受檢異常,一般是由於運行時的各種意外情況導致程序運行異常,所以很多人習慣稱之爲運行時異常,這類異常均繼承自RuntimeException。Java語言不強制對這類異常進行捕獲,但是仍可以進行手動捕獲,來避免可能發生的意外

同樣地,我們仍可以對這一類異常做進一步的劃分:

  • 可預測異常(Predicted Exception):可以預測到會發生的異常,一般是由於代碼錯誤或外部因素導致
  • 警告級異常(Caution Exception):需要進行顯式的捕獲處理的異常,否則就會導致程序不可用
  • 可忽略異常(Ignored Exception):程序或框架會自行處理的異常,程序員可以忽略

可預測異常,最常見的就是NullPointerException(空指針異常)和IndexOutOfBoundsException(數據越界異常),這類異常我們完全可以通過提前檢查來進行避免

Java不要求我們強制捕獲這類異常,一個原因是這類異常在任何需要傳入對象參數的函數中都要進行捕獲,如果強制捕獲會導致代碼過長,另一個原因是這類異常的捕獲完全可以通過參數檢驗來代替,使用性能低下的try-catch反而是一種不良的編碼習慣

警告級異常,也有地方叫做需捕捉異常,一般是由一些框架的基礎方法拋出,因爲這類異常如果發生會導致整個服務不可用,所以需要進行捕獲處理,比如超時異常之類

可忽略異常,這類異常通常我們見不到,因爲基本都由底層框架來進行處理,我們只需要知道這類異常不由程序員進行捕獲處理就可以了

總結

整個Java的異常分類就是這樣了,我在下面總結了一幅圖,來作爲整篇文章的收尾:
總結

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章