關鍵詞偽泛型針對引用的檢查型別擦除協變多型的衝突一、介紹
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>);
最新評論