問題提出場景
近期在看《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
的,這只是普通的限定符,和泛型類並無多大關聯,爲以防造成誤解,特此提出。