爲什麼泛型類無法繼承自 Throwable

問題提出場景

近期在看《Java 核心技術卷I》第八章泛型程序設計時提到泛型類是無法繼承自 Throwable,倘若我們在 IDE 中寫上類似 public class CustomException<T> extends Throwable 的代碼,那麼 IDE 會提示我們 Genergic class may not extends ‘java.lang.Throwable’。關於原因書上未做詳盡解釋,於是自己在 StackOverflow 上找到了答案,答案鏈接請戳我

原因

結合實例分析原因:

try {
    // may throws exception
    doSomeStuff();
} catch (SomeException<Integer> e) {
    doA();
} catch (SomeException<String> e) {
    doB();
}

假設當前我們有兩個類 —— SomeException<Integer> 類和 SomeException<String> 類,它們都是繼承自 Throwable 類的。而上述代碼中的 doSomeStuff() 方法可能是拋出 SomeException<Integer> 異常或 SomeException<String> 異常,我們針對不同的異常做出不同的邏輯操作。這樣看似完全沒有問題,但是熟悉泛型的小夥伴都知道,還有一種叫做類型擦除機制的存在,何爲類型擦除?此處不擴展了,通俗點說:java 中不存在泛型代碼,泛型代碼是寫給我們看的,編譯器會將泛型代碼轉換成普通類代碼。所以無論是 SomeException<Integer> 或者是 SomeException<String> 經過編譯器的類型擦除後都將會變成 SomeException。故上述代碼是不可以運行的,因爲當代碼拋出異常時編譯器是無法判斷走哪個 catch 分支的,所以 java 爲了避免這樣的問題出現,故泛型類是無法繼承自 Throwable 類的。

後言

類型擦除作爲筆者本身來說還是瞭解一些的,最開始碰到這個問題無法下手的原因還是缺少實踐,沒有想到類似上述代碼的實際場景,導致不能夠理解該問題。最後,本博客說的是泛型類無法繼承自 Throwable,而並不是泛型不能繼承自 Throwable。例如以下代碼是合法的:

public class Test<T extends Throwable> {}

泛型 T 是可以繼承自 Throwable 的,這只是普通的限定符,和泛型類並無多大關聯,爲以防造成誤解,特此提出。

發佈了41 篇原創文章 · 獲贊 81 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章