【夯實Java基礎07】你對 Java 異常瞭解多少?看看面試官都喜歡問什麼?

武哥聊程式設計發表於2021-01-03

本文已收錄至我的GitHub:Java開發寶典,歡迎大家給個Star:https://github.com/eson15/javaAll
我會持續更新,歡迎star!
微信搜尋:武哥聊程式設計,回覆“筆記”,可以領取一份我親自寫的10萬字Springboot經典學習筆記一份



1. 異常的概念

如果某個方法不能按照正常的途徑完成任務,就可以通過另一種路徑退出方法。在這種情況下會丟擲一個封裝了錯誤資訊的物件。此時,這個方法會立刻退出同時不返回任何值。另外,呼叫這個方法的其他程式碼也無法繼續執行,異常處理機制會將程式碼執行交給異常處理器。

Java異常概念

2. Java 中異常分為哪些種類

按照異常需要處理的時機分為編譯時異常(也叫強制性異常)也叫CheckedException 和執行時異常(也叫非強制性異常)也叫RuntimeException。

只有java 語言提供了Checked 異常,Java 認為 Checked 異常都是可以被處理的異常,所以Java 程式必須顯式處理Checked 異常。如果程式沒有處理Checked 異常,該程式在編譯時就會發生錯誤無法編譯。這體現了Java 的設計哲學:沒有完善錯誤處理的程式碼根本沒有機會被執行。對Checked 異常處理方法有兩種:

  1. 當前方法知道如何處理該異常,則用try…catch 塊來處理該異常。
  2. 當前方法不知道如何處理,則在定義該方法是宣告丟擲該異常。

執行時異常只有當程式碼在執行時才發行的異常,編譯時不需要try catch。Runtime 如除數是0 和陣列下標越界等,其產生頻繁,處理麻煩,若顯示申明或者捕獲將會對程式的可讀性和執行效率影響很大。所以由系統自動檢測並將它們交給預設的異常處理程式。當然如果你有處理要求也可以顯示捕獲它們。

那麼,呼叫下面的方法,會得到什麼結果呢?

public int getNum(){
	try {
		int a = 1/0;
		return 1;
	} catch (Exception e) {
		return 2;
	}finally{
		return 3;
	}
}

程式碼在走到第3 行的時候遇到了一個MathException,這時第四行的程式碼就不會執行了,程式碼直接跳轉到catch語句中,走到第6 行的時候,異常機制有這麼一個原則如果在catch 中遇到了return 或者異常等能使該函式終止的話那麼有finally 就必須先執行完finally 程式碼塊裡面的程式碼然後再返回值。因此程式碼又跳到第8 行,可惜第8 行是一個return 語句,那麼這個時候方法就結束了,因此第6 行的返回結果就無法被真正返回。如果finally 僅僅是處理了一個釋放資源的操作,那麼該道題最終返回的結果就是2。因此上面返回值是3。

微信搜尋:武哥聊程式設計,回覆“筆記”,可以免費領取一份我親自寫的10萬字Springboot經典學習筆記一份

3. error 和exception 有什麼區別?

Error 類和Exception 類的父類都是Throwable 類,他們的區別如下。
Error 類一般是指與虛擬機器相關的問題,如系統崩潰,虛擬機器錯誤,記憶體空間不足,方法呼叫棧溢位等。對於這類錯誤的導致的應用程式中斷,僅靠程式本身無法恢復和和預防,遇到這樣的錯誤,建議讓程式終止。
Exception 類表示程式可以處理的異常,可以捕獲且可能恢復。遇到這類異常,應該儘可能處理異常,使程式恢復執行,而不應該隨意終止異常。
Exception 類又分為執行時異常(Runtime Exception)和受檢查的異常(Checked Exception ),執行時異常;ArithmaticException,IllegalArgumentException,編譯能通過,但是一執行就終止了,程式不會處理執行時異常,出現這類異常,程式會終止。而受檢查的異常,要麼用try。。。catch 捕獲,要麼用throws 字句宣告丟擲,交給它的父類處理,否則編譯不會通過。

4. throw 和 throws 的區別是什麼?

Java 中的異常處理除了包括捕獲異常和處理異常之外,還包括宣告異常和丟擲異常,可以通過 throws 關鍵字在方法上宣告該方法要丟擲的異常,或者在方法內部通過 throw 丟擲異常物件。

throws 關鍵字和 throw 關鍵字在使用上的幾點區別如下:

  1. throw 關鍵字用在方法內部,只能用於丟擲一種異常,用來丟擲方法或程式碼塊中的異常,受查異常和非受查異常都可以被丟擲。
  2. throws 關鍵字用在方法宣告上,可以丟擲多個異常,用來標識該方法可能丟擲的異常列表。一個方法用 throws 標識了可能丟擲的異常列表,呼叫該方法的方法中必須包含可處理異常的程式碼,否則也要在方法簽名中用 throws 關鍵字宣告相應的異常。

5. Java 的異常處理機制

Java 對異常進行了分類,不同型別的異常分別用不同的Java 類表示,所有異常的根類為java.lang.Throwable,Throwable 下面又派生了兩個子類:Error 和Exception,Error 表示應用程式本身無法克服和恢復的一種嚴重問題。
Exception 表示程式還能夠克服和恢復的問題,其中又分為系統異常和普通異常,系統異常是軟體本身缺陷所導致的問題,也就是軟體開發人員考慮不周所導致的問題,軟體使用者無法克服和恢復這種問題,但在這種問題下還可以讓軟體系統繼續執行或者讓軟體死掉,例如,陣列指令碼越界(ArrayIndexOutOfBoundsException),空指標異常(NullPointerException)、類轉換異常(ClassCastException);普通異常是執行環境的變化或異常所導致的問題,是使用者能夠克服的問題,例如,網路斷線,硬碟空間不夠,發生這樣的異常後,程式不應該死掉。java 為系統異常和普通異常提供了不同的解決方案,編譯器強制普通異常必須try…catch 處理或用throws 宣告繼續拋給上層呼叫方法處理,所以普通異常也稱為checked 異常,而系統異常可以處理也可以不處理,所以,編譯器不強制用try…catch 處理或用throws 宣告,所以系統異常也稱為unchecked 異常。

6. 請寫出你最常見的5 個RuntimeException

這是面試過程中,很喜歡問的問題,下面列舉幾個常見的RuntimeException。

1)java.lang.NullPointerException 空指標異常;出現原因:呼叫了未經初始化的物件或者是不存在的物件。
2)java.lang.ClassNotFoundException 指定的類找不到;出現原因:類的名稱和路徑載入錯誤;通常都是程式試圖通過字串來載入某個類時可能引發異常。
3)java.lang.NumberFormatException 字串轉換為數字異常;出現原因:字元型資料中包含非數字型字元。
4)java.lang.IndexOutOfBoundsException 陣列角標越界異常,常見於運算元組物件時發生。
5)java.lang.IllegalArgumentException 方法傳遞引數錯誤。
6)java.lang.ClassCastException 資料型別轉換異常。
7)java.lang.NoClassDefFoundException 未找到類定義錯誤。
8)SQLException SQL 異常,常見於運算元據庫時的SQL 語句錯誤。
9)java.lang.InstantiationException 例項化異常。
10)java.lang.NoSuchMethodException 方法不存在異常。

7. final、finally、finalize 的區別

1)final:用於宣告屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,被其修飾的類不可繼承。
2)finally:異常處理語句結構的一部分,表示總是執行。
3)finalize:Object 類的一個方法,在垃圾回收器執行的時候會呼叫被回收物件的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關閉檔案等。該方法更像是一個物件生命週期的臨終方法,當該方法被系統呼叫則代表該物件即將“死亡”,但是需要注意的是,我們主動行為上去呼叫該方法並不會導致該物件“死亡”,這是一個被動的方法(其實就是回撥方法),不需要我們呼叫。

8. NoClassDefFoundError 和 ClassNotFoundException 區別

NoClassDefFoundError 是一個 Error 型別的異常,是由 JVM 引起的,不應該嘗試捕獲這個異常。

引起該異常的原因是 JVM 或 ClassLoader 嘗試載入某類時在記憶體中找不到該類的定義,該動作發生在執行期間,即編譯時該類存在,但是在執行時卻找不到了,可能是變異後被刪除了等原因導致;

ClassNotFoundException 是一個受查異常,需要顯式地使用 try-catch 對其進行捕獲和處理,或在方法簽名中用 throws 關鍵字進行宣告。當使用 Class.forName, ClassLoader.loadClass 或 ClassLoader.findSystemClass 動態載入類到記憶體的時候,通過傳入的類路徑引數沒有找到該類,就會丟擲該異常;另一種丟擲該異常的可能原因是某個類已經由一個類載入器載入至記憶體中,另一個載入器又嘗試去載入它。

Java 異常 就總結這麼多,如果有問題,歡迎討論。

作者info

【作者】:武哥
【公眾號】:武哥聊程式設計。歡迎大家關注~
【作者簡介】:同濟大學,碩士。先後在華為、科大訊飛、拼多多采坑。一個自學 Java 的菜鳥,期待你的關注。

點贊是對我最大的鼓勵
↓↓↓↓↓↓

相關文章