在 JDK 1.5 中,以下兩種寫法語意相同,但編譯結果截然不同:
Object obj = new Test();
// 寫法一:方法鏈 - 編譯通過
((Test)obj).getClass().newInstance().func();
// 寫法二:分步賦值 - 編譯失敗
Class c = ((Test)obj).getClass();
c.newInstance().func();
JDK 1.5 引入泛型後,Object.getClass() 簽名變為:
public final Class<? extends Object> getClass()
返回類型為 Class<? extends X>,其中 X 為呼叫端的靜態類型。
((Test)obj) 靜態類型為 TestgetClass() 返回 Class<? extends Test>Class<T>.newInstance() 返回類型 T? extends Test 的實例類型為 Test,故 newInstance() 返回 Test,可呼叫 func()Class<? extends Test> 強制轉為原始類型 Class (Raw Type)Class.newInstance() 返回類型退化為 ObjectObject 無 func() 方法,編譯錯誤使用有界通配符保留泛型資訊:
Class<? extends Test> c = ((Test)obj).getClass();
c.newInstance().func(); // 編譯通過
或顯式轉型:
Class c = ((Test)obj).getClass();
((Test)c.newInstance()).func(); // 編譯通過但有非檢查轉型警告
Class<? extends T> 而非 Raw Type 可最大化類型安全