首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JDK 1.5 編譯器泛型推導的奇特行為分析

     編輯:Java 相關知識

現象描述

在 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) 靜態類型為 Test
  • getClass() 返回 Class<? extends Test>
  • Class<T>.newInstance() 返回類型 T
  • 編譯器推導 ? extends Test 的實例類型為 Test,故 newInstance() 返回 Test,可呼叫 func()

寫法二分析

  • 將 Class<? extends Test> 強制轉為原始類型 Class (Raw Type)
  • Class.newInstance() 返回類型退化為 Object
  • Object 無 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 可最大化類型安全
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved