Java中的Type


原文:https://www.cnblogs.com/linghu-java/p/8067886.html

 

Type是Java 編程語言中所有類型的公共高級接口(官方解釋),也就是Java中所有類型的“爹”;其中,“所有類型”的描述尤為值得關注。它並不是我們平常工作中經常使用的 int、String、List、Map等數據類型,而是從Java語言角度來說,對基本類型、引用類型向上的抽象;

Type體系中類型的包括:原始類型(Class)、參數化類型(ParameterizedType)、數組類型(GenericArrayType)、類型變量(TypeVariable)、基本類型(Class);

原始類型,不僅僅包含我們平常所指的類,還包括枚舉、數組、注解等;

參數化類型,就是我們平常所用到的泛型List、Map;

數組類型,並不是我們工作中所使用的數組String[] 、byte[],而是帶有泛型的數組,即T[] ;

基本類型,也就是我們所說的java的基本類型,即int,float,double等

 

 
空接口

Type是個空接口,沒有定義任何方法,通過多態提高了程序的擴展性,具體實現去看下面的子類;

 

 
Type體系

查看源碼,Type接口下共有4個"兒子",每一個“兒子”代表着Java中的一種類型;

1.ParameterizedType

參數化類型,即泛型;例如:List<T>、Map<K,V>等帶有參數化的對象;

 
ParameterizedType源碼

2.TypeVariable

類型變量,即泛型中的變量;例如:T、K、V等變量,可以表示任何類;在這需要強調的是,TypeVariable代表着泛型中的變量,而ParameterizedType則代表整個泛型;

 

 
TypeVariable源碼

3.GenericArrayType

泛型數組類型,用來描述ParameterizedType、TypeVariable類型的數組;即List<T>[] 、T[]等;

 

 
GenericArrayType源碼

 

4.Class

上三者不同,Class是Type的一個實現類,屬於原始類型,是Java反射的基礎,對Java類的抽象;

在程序運行期間,每一個類都對應一個Class對象,這個對象包含了類的修飾符、方法,屬性、構造等信息,所以我們可以對這個Class對象進行相應的操作,這就是Java的反射;

5.WildcardType

泛型表達式(或者通配符表達式),即? extend Number、? super Integer這樣的表達式;WildcardType雖然是Type的子接口,但卻不是Java類型中的一種;

 

 
WildcardType源碼

以上,簡單介紹了Java-Type的體系;為了解決泛型,JDK1.5版本開始引入Type接口;在此之前,Java中只有原始類型,所有的原始類型都是通過Class進行抽象;有了Type以后,Java的數據類型得到了擴展,從原始類型擴展為參數化類型(ParameterizedType)、數組類型(GenericArrayType)、類型變量(TypeVariable);

 

下面就用代碼的方式,對其中的5大類型:原始類型(Class)、參數化類型(ParameterizedType)、數組類型(GenericArrayType)、類型變量(TypeVariable)、基本類型(Class) 進一步說明;

1.ParameterizedType

ParameterizedType表示參數化類型,也就是泛型,例如List<T>、Set<T>等;

 
ParameterizedType
 
 

在ParameterizedType接口中,有3個方法,分別是getActualTypeArguments()、 getRawType()、 getOwnerType();

1.1 getActualTypeArguments

獲取泛型中的實際類型,可能會存在多個泛型,例如Map<K,V>,所以會返回Type[]數組;

 
 

值得注意的是,無論<>中有幾層嵌套(List<Map<String,Integer>),getActualTypeArguments()方法永遠都是脫去最外層的<>(也就是List<>),將口號內的內容(Map<String,Integer>)返回;

我們經常遇到的List<T>,通過getActualTypeArguments()方法,得到的返回值是TypeVariableImpl對象,也就是TypeVariable類型(后面介紹);

1.2 getRawType

獲取聲明泛型的類或者接口,也就是泛型中<>前面的那個值;

 
 
 

1.3 getOwnerType

通過方法的名稱,我們大概了解到,此方法是獲取泛型的擁有者,那么擁有者是個什么意思?

Returns a {@code Type} object representing the type that this type    * is a member of.  For example, if this type is {@code O.I},    * return a representation of {@code O}.  (摘自JDK注釋)

通過注解,我們得知,“擁有者”表示的含義--內部類的“父類”,通過getOwnerType()方法可以獲取到內部類的“擁有者”;例如: Map  就是 Map.Entry<String,String>的擁有者;

 
 

2.GenericArrayType

泛型數組類型,例如List<String>[] 、T[]等;

 
GenericArrayType

在GenericArrayType接口中,僅有1個方法,就是getGenericComponentType();

2.1 getGenericComponentType

返回泛型數組中元素的Type類型,即List<String>[] 中的 List<String>(ParameterizedTypeImpl)、T[] 中的T(TypeVariableImpl);

 
 

值得注意的是,無論是幾維數組,getGenericComponentType()方法都只會脫去最右邊的[],返回剩下的值;

3.TypeVariable

泛型的類型變量,指的是List<T>、Map<K,V>中的T,K,V等值,實際的Java類型是TypeVariableImpl(TypeVariable的子類);此外,還可以對類型變量加上extend限定,這樣會有類型變量對應的上限;

 
TypeVariable

在TypeVariable接口中,有3個方法,分別為getBounds()、getGenericDeclaration()、getName();

3.1 getBounds

獲得該類型變量的上限,也就是泛型中extend右邊的值;例如 List<T extends Number> ,Number就是類型變量T的上限;如果我們只是簡單的聲明了List<T>(無顯式定義extends),那么默認為Object;

 
 

無顯式定義extends:

 
 

值得注意的是,類型變量的上限可以為多個,必須使用&符號相連接,例如 List<T extends Number & Serializable>;其中,& 后必須為接口;

3.2 getGenericDeclaration

獲取聲明該類型變量實體,也就是TypeVariableTest<T>中的TypeVariableTest;

 
 

3.3 getName

獲取類型變量在源碼中定義的名稱;

 
 

說到TypeVariable類,就不得不提及Java-Type體系中另一個比較重要的接口---GenericDeclaration;含義為:聲明類型變量的所有實體的公共接口;也就是說該接口定義了哪些地方可以定義類型變量(泛型);

通過查看源碼發現,GenericDeclaration下有三個子類,分別為Class、Method、Constructor;也就是說,我們定義泛型只能在一個類中這3個地方自定義泛型;

 
 

此時,我們不禁要問,我們不是經常在類中的屬性聲明泛型嗎,怎么Field沒有實現 GenericDeclaration接口呢?

其實,我們在Field中並沒有聲明泛型,而是在使用泛型而已!不信,我們實際上代碼來看看!

1.首先在Class上定義泛型:

 
Class定義泛型

2.我們沒有在Class上定義泛型,直接在構造方法上定義泛型

 
泛型構造

3.同樣沒有在Class定義泛型,直接在普通方法上定義泛型

 
泛型方法

3.我們直接在屬性上定義

 
屬性上定義泛型

我們看到,如果不在Class上定義,屬性上並不能直接使用!所以,這也是我之前說的屬性上並不是定義泛型,而是使用泛型,所以Field並沒有實現GenericDeclaration接口!

4.Class

Type接口的實現類,是我們工作中常用到的一個對象;在Java中,每個.class文件在程序運行期間,都對應着一個Class對象,這個對象保存有這個類的全部信息;因此,Class對象也稱之為Java反射的基礎;

 
Class

通過上面的例子,可以看出,當我們沒有聲明泛型的時候,我們普通的對象就是一個Class類型,是Type中的一種;

5.WildcardType

?---通配符表達式,表示通配符泛型,但是WildcardType並不屬於Java-Type中的一鍾;例如:List<? extends Number> 和 List<? super Integer>;

 
WildcardType

在WildcardType接口中,有2個方法,分別為getUpperBounds()、getLowerBounds();

5.1 getUpperBounds

獲取泛型變量的上邊界(extends)

 
 

5.2 getLowerBounds

獲取泛型變量的下邊界(super)

 
 

以上,就是對Java-Type體系中相關對象的介紹;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM