首頁>技術>

關鍵詞偽泛型針對引用的檢查型別擦除協變多型的衝突一、介紹

java泛型是偽泛型,java檔案編譯時會進行型別擦除這樣生成的class檔案不再包含任何泛型資訊。泛型價值:增加約束,讓程式碼優雅(無需顯式的型別轉化)。

二、原始型別
abstract class Math<T> {    abstract T max(T t1, T t2);}-----位元組碼------abstract max(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;abstract class Math2<T extends Number> {    abstract T max(T t1, T t2);}------位元組碼-----abstract max(Ljava/lang/Number;Ljava/lang/Number;)Ljava/lang/Number;

Object 或者 Number 就是T 的原始型別。這是型別擦除的基礎思路,也由此產生了多型衝突問題。

三、型別擦除

文字描述比較枯燥難懂,以下透過3個示例來介紹,型別擦除、針對引用有效、為什麼叫做 偽泛型。

示例1

// 攜帶泛型的物件對應位元組碼完全一致。   List<String> strList = new ArrayList<String>();   List intList = new ArrayList();---------位元組碼------------   NEW java/util/ArrayList   DUP   INVOKESPECIAL java/util/ArrayList.<init> ()V   ASTORE 1   NEW java/util/ArrayList   DUP   INVOKESPECIAL java/util/ArrayList.<init> ()V   ASTORE 2

示例2

 /** * 約定泛型的list,可以透過反射成功新增 int型別資料進去,透過反射可以正常讀取,直接讀取時會提示型別轉化異常。 */@Testpublic void typeErasure() {    try {        List<String> strList = new ArrayList();        strList.getClass().getMethod("add", Object.class).invoke(strList, 123);        System.out.println("strList'size :" + strList.size());        System.out.println(strList.getClass().getMethod("get", int.class).invoke(strList, 0));        System.out.println(strList.get(Integer.valueOf(0)));    } catch (Exception e) {        e.printStackTrace();    }}

示例3

泛型針對引用有效。List<String> strList1 = new ArrayList();//有效果(阿里巴巴規範也提倡這麼寫)List<String> strList2 = new ArrayList<String>();//效果同上面List strList3 = new ArrayList<String>();//無效果

由於 泛型僅僅生存到編譯時期,所以稱之為 偽泛型。

四、多型的衝突
abstract class Math<T> {    abstract T max(T t1, T t2);}-------二進位制碼---------abstract max(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;class IntMath extends Math<Integer> {    @Override    Integer max(Integer t1, Integer t2) {        return java.lang.Math.max(t1, t2);    }}--------二進位制碼--------max(Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer;synthetic bridge max(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;   L0    LINENUMBER 28 L0    ALOAD 0    ALOAD 1    CHECKCAST java/lang/Integer    ALOAD 2    CHECKCAST java/lang/Integer    INVOKEVIRTUAL com/hardydou/jmm/IntMath.max (Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer;    ARETURN

泛型子類重寫不是簡單的重寫,而是過載+重寫

五、實戰5.1、基本型別不可以作為泛型
List<int> list;//編譯不透過
5.2、泛型不可以被例項化
class A<T> {    T t=new T();//不可以被直接例項化    ....... }
5.2、泛型使用instanceOf
List<String> list1 = new ArrayList<>();//可以boolean s1 = (list1 instanceof ArrayList<?>);boolean s3 = (list1 instanceof ArrayList);//編譯報錯boolean s2 = (list1 instanceof ArrayList<String>);

4
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 必須瞭解的十個高階SQL概念