Java異常類體系和異常處理

一、概念介紹

異常是發生在程序執行過程中阻礙程序正常執行的錯誤事件,當一個程序出現錯誤時,可能的情況分為以下3種:

1、語法錯誤:代碼的格式錯了,某個字母輸錯了

2、運行時錯誤:空指針異常,數組越界,除數為零等

3、邏輯錯誤:運行結果與預想的結果不一樣,這是一種很難調試的錯誤Java中的異常處理機制主要處理運行時錯誤。

下圖是一張經典的Java異常類層次結構圖,對各種異常做出了較為清晰的分類:

Java異常體系分類

從上圖中可以看到,所有的異常都繼承自一個共同的父類Throwable,而Throwable有兩個重要的子類:Exception(異常)和Error(錯誤)。

二、error和exception有什么區別?

這個是面試中經常會問到的,下面對這兩個重要的子類進行介紹:

Error(錯誤)

1、 是程序無法處理的錯誤,表示運行應用程序中較嚴重問題。大多數錯誤與代碼編寫者執行的操作無關,而表示代碼運行時 JVM(Java 虛擬機)出現的問題。例如,Java虛擬機運行錯誤(Virtual MachineError),當 JVM 不再有繼續執行操作所需的內存資源時,將出現 OutOfMemoryError。這些異常發生時,Java虛擬機(JVM)一般會選擇線程終止。

2、 這些錯誤表示故障發生于虛擬機自身、或者發生在虛擬機試圖執行應用時,如Java虛擬機運行錯誤(Virtual MachineError)、類定義錯誤(NoClassDefFoundError)等。這些錯誤是不可查的,因為它們在應用程序的控制和處理能力之 外,而且絕大多數是程序運行時不允許出現的狀況。對于設計合理的應用程序來說,即使確實發生了錯誤,本質上也不應該試圖去處理它所引起的異常狀況。在 Java中,錯誤通過Error的子類描述。

Exception(異常)

1、 是程序本身可以處理的異常。主要包含RuntimeException等運行時異常和IOException,SQLException等非運行時異常。

2、運行時異常包括:都是RuntimeException類及其子類異常,如NullPointerException(空指針異常)、IndexOutOfBoundsException(下標越界異常)等,這些異常是不檢查異常,程序中可以選擇捕獲處理,也可以不處理。這些異常一般是由程序邏輯錯誤引起的,程序應該從邏輯角度盡可能避免這類異常的發生。

3、 運行時異常的特點是Java編譯器不會檢查它,也就是說,當程序中可能出現這類異常,即使沒有用try-catch語句捕獲它,也沒有用throws子句聲明拋出它,也會編譯通過。

4、非運行時異常(編譯異常)包括:RuntimeException以外的異常,類型上都屬于Exception類及其子類。從程序語法角度講是必須進行處理的異常,如果不處理,程序就不能編譯通過。如IOException、SQLException等以及用戶自定義的Exception異常,一般情況下不自定義檢查異常。

編譯器是否要求強制處理的角度分類,異常類別又可分為:

a、可查異常

b、正確的程序在運行中,很容易出現的、情理可容的異常狀況。可查異常雖然是異常狀況,但在一定程度上它的發生是可以預計的,而且一旦發生這種異常狀況,就必須采取某種方式進行處理。

c、除了RuntimeException及其子類以外,其他的Exception類及其子類都屬于可查異常。這種異常的特點是Java編譯器會檢查它,也就是說,當程序中可能出現這類異常,要么用try-catch語句捕獲它,要么用throws子句聲明拋出它,否則編譯不會通過。

三、異常處理機制

在 Java 應用程序中,異常處理機制為:拋出異常,捕捉異常。

1、拋出異常

a、當一個方法出現錯誤引發異常時,方法創建異常對象并交付運行時系統,異常對象中包含了異常類型和異常出現時的程序狀態等異常信息。運行時系統負責尋找處置異常的代碼并執行。

b、注意:對于運行時異常、錯誤或可查異常,Java技術所要求的異常處理方式有所不同。

c、由于運行時異常的不可查性,為了更合理、更容易地實現應用程序,Java規定,運行時異常將由Java運行時系統自動拋出,允許應用程序忽略運行時異常。

d、對于方法運行中可能出現的Error,當運行方法不欲捕捉時,Java允許該方法不做任何拋出聲明。因為,大多數Error異常屬于永遠不能被允許發生的狀況,也屬于合理的應用程序不該捕捉的異常。

e、對于所有的可查異常,Java規定:一個方法必須捕捉,或者聲明拋出方法之外。也就是說,當一個方法選擇不捕捉可查異常時,它必須聲明將拋出異常

2、捕獲異常

a、在方法拋出異常之后,運行時系統將轉為尋找合適的異常處理器(exception handler)。潛在的異常處理器是異常發生時依次存留在調用棧中的方法的集合。當異常處理器所能處理的異常類型與方法拋出的異常類型相符時,即為合適 的異常處理器。運行時系統從發生異常的方法開始,依次回查調用棧中的方法,直至找到含有合適異常處理器的方法并執行。當運行時系統遍歷調用棧而未找到合適 的異常處理器,則運行時系統終止。同時,意味著Java程序的終止。

通常使用關鍵字try、catch、finally來捕獲異常

語法形式如下:

try {
    //可能出現異常的代碼
} catch (Exception e) {
    //異常處理的相關代碼(三種方案)
    //方案1:自定義處理, 如println();
    //方案2:打印堆棧跟蹤信息, e.printStackTrace();
    //方案3:獲取異常的原因信息, println(e.getMessage());
[... 多重 catch () ...] // 遵循從子到父的順序,父類異常在最后。
} finally {
    //無論是否出現異常都需要執行的代碼結構(不受return影響),常用于釋放資源
}

小結:

try 塊:用于捕獲異常。其后可接零個或多個catch塊,如果沒有catch塊,則必須跟一個finally塊。

catch 塊:用于處理try捕獲到的異常。

finally 塊:無論是否捕獲或處理異常,finally塊里的語句都會被執行。當在try塊或catch塊中遇到return語句時,finally語句塊將在方法返回之前被執行。在以下4種特殊情況下,finally塊不會被執行:

1、在finally語句塊中發生了異常。

2、在前面的代碼中用了System.exit()退出程序。

3、程序所在的線程死亡。

4、關閉CPU。

四、try、catch、finally語句塊的執行順序

1、當try沒有捕獲到異常時:try語句塊中的語句逐一被執行,程序將跳過catch語句塊,執行finally語句塊和其后的語句;

2、當try捕獲到異常,catch語句塊里沒有處理此異常的情況:當try語句塊里的某條語句出現異常時,而沒有處理此異常的catch語句塊時,此異常將會拋給JVM處理,finally語句塊里的語句還是會被執行,但finally語句塊后的語句不會被執行;

3、當try捕獲到異常,catch語句塊里有處理此異常的情況:在try語句塊中是按照順序來執行的,當執行到某一條語句出現異常時,程序將跳到catch語句塊,并與catch語句塊逐一匹配,找到與之對應的處理程序,其他的catch語句塊將不會被執行,而try語句塊中,出現異常之后的語句也不會被執行,catch語句塊執行完后,執行finally語句塊里的語句,最后執行finally語句塊后的語句;

流程如下圖所示:

image.png

五、面試常考問題總結

1、在Java中throw與throws關鍵字之間的區別?

throws用于在方法簽名中聲明此方法可能拋出的異常,而throw關鍵字則是中斷程序的執行并移交異常對象到運行時進行處理。

2.Java中final,finally,finalize的區別?

final和finally在Java中是關鍵字,而finalize則是一個方法。

final關鍵字使得類變量不可變,避免類被其它類繼承或方法被重寫。

finally跟try-catch塊一起使用,即使是出現了異常,其子句總會被執行,通常,finally子句用來關閉相關資源。

finalize方法中的對象被銷毀之前會被垃圾回收。

3.被檢查的異常和不受檢查的異常有什么區別?

被檢查的異常應該用try-catch塊代碼處理,或者在main方法中用throws關鍵字讓JRE了解程序可能拋出哪些異常。不受檢查的異常在程序中不要求被處理或用throws語句告知。

Exception是所有被檢查異常的基類,然而,RuntimeException是所有不受檢查異常的基類

被檢查的異常適用于那些不是因程序引起的錯誤情況,比如:讀取文件時文件不存在引發的FileNotFoundException。然而,不被檢查的異常通常都是由于糟糕的編程引起的,比如:在對象引用時沒有確保對象非空而引起的NullPointerException。

4、描述Java 7 ARM(Automatic Resource Management,自動資源管理)特征和多個catch塊的使用

如果一個try塊中有多個異常要被捕獲,catch塊中的代碼會變丑陋的同時還要用多余的代碼來記錄異常。有鑒于此,Java 7的一個新特征是:一個catch子句中可以捕獲多個異常。

大多數情況下,當忘記關閉資源或因資源耗盡出現運行時異常時,我們只是用finally子句來關閉資源。這些異常很難調試,我們需要深入到資源使用的每一步來確定是否已關閉。因此,Java 7用try-with-resources進行了改進:在try子句中能創建一個資源對象,當程序的執行完try-catch之后,運行環境自動關閉資源。下面是這方面改進的示例代碼:

5.下面是一些代碼相關的問題,需要回答該代碼有沒有問題?該怎么修改?

A.下面這段代碼有什么問題呢?

上面代碼的主要問題在于FileNotFoundException是IOException的子類,編譯會報錯:The exception FileNotFoundException is already caught by the alternative IOException.

有兩種辦法可以解決這個問題

①、用兩個catch子句來處理這兩個異常

②、在catch子句中移除FileNotFoundException,只用IOException

image
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380