java泛型的理解,和爲什麼擦出後,還可以得到

java泛型的理解,和爲什麼擦出後,還可以得到

開篇

泛型的使用和例子不說了,太多同類型的文章,自己搜搜,本文主要說
  • 泛型的來源和影響
  • 泛型擦除
  • 泛型擦除了,爲什麼反射時還可以得到

泛型的來源和影響

在1.5之前沒有泛型的只有class,所有的類都是class,也就是原始類型,我們統一定義了一個class類進行抽象,class類的一個具體對象就是一個類,後面有了泛型,超出了原始類型的定義,我們給class增加了4個平級的類型,他們是,1)參數化類型,就是用了泛型的類。2)類型變量類型,就是泛型裏面的那個類型變量。3)泛型表達式類型 4)參數化泛型數組類型。這些都是和原始類型平齊的。
但是jvm只可以處理class原始類型,這個是java一開始就定義好的,如果要改的話,就是要在jvm中增加4中字節碼文件,對於jvm改的太大,所以我們不改,在javac編譯階段做兼容。這個也就是爲什麼我們說java的泛型是僞泛型,因爲jvm並不支持泛型

泛型擦除

泛型擦除,就是在編譯階段,把我們寫的泛型轉化爲jvm所支持的原始類型,也就是class類型,並且保持語法不變。這個中間過程很複雜。網上專門解釋的文章很多。記住就是jvm不認識我們書寫的泛型,javac要做一層轉化。這個也就是意味着我們在jvm中,也就是在運行中執行的代碼,沒有泛型的代碼。

泛型擦除了,爲什麼反射時還可以得到

我們在上面說的泛型既然被擦除了,爲什麼反射時還可以得到我們書寫的泛型呢,這個我找了很多資料才發現,爲了方便反射操作,我們在java中定義了一個頂層接口 type他有

  • ParameterizedType: 表示一種參數化的類型,比如Collection
  • GenericArrayType: 表示一種元素類型是參數化類型或者類型變量的數組類型
  • TypeVariable: 是各種類型變量的公共父接口
  • WildcardType: 代表一種通配符類型表達式,比如?, ? extends Number, ? superInteger【wildcard是一個單詞:就是“通配符”】

就是我們用class類型表示我們上面說的和原始類型平齊的4種類型,方便我們反射的時候使用,獲得泛型的數據。下面我們來回答上面的問題
最後我看資料發現原來javac在編譯的時候,確實在代碼上把泛型都轉化爲原始類型了,也就是實現了擦除,要不然也運行不了,但是對於類,方法和屬性的泛型(方法體內部除外)。javac編譯的時候專門在字節碼中分配一個元數據存放 叫做Signature。存放我們泛型信息,方便反射可以得到

import java.util.List;  
import java.util.Map;  
  
public class GenericClass<T> {                // 1  
    private List<T> list;                     // 2  
    private Map<String, T> map;               // 3  
      
    public <U> U genericMethod(Map<T, U> m) { // 4  
        return null;  
    }  
} 

//字節碼
private java.util.Map map;  
  Signature: Ljava/util/Map;  
  Signature: length = 0x2  
   00 0A 
//字節碼
const #10 = Asciz       Ljava/util/Map<Ljava/lang/String;TT;>;;  

我下面貼幾個比較好的,對我有幫助的鏈接

[添加鏈接描述](http://www.cnblogs.com/mylove7/articles/5811748.html)
[添加鏈接描述](http://rednaxelafx.iteye.com/blog/586212)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章