Type
下面就用代碼的方式,對其中的5大類型:原始類型(Class)、參數化類型(ParameterizedType)、數組類型(GenericArrayType)、類型變量(TypeVariable)、基本類型(Class) 進一步說明;
1.ParameterizedType
ParameterizedType表示參數化類型,也就是泛型,例如List、Set等;
ParameterizedType
在ParameterizedType接口中,有3個方法,分別是getActualTypeArguments()、 getRawType()、 getOwnerType();
1.1 getActualTypeArguments
獲取泛型中的實際類型,可能會存在多個泛型,例如Map,所以會返回Type[]數組;
值得注意的是,無論<>中有幾層嵌套(List),getActualTypeArguments()方法永遠都是脫去最外層的<>(也就是List<>),將口號內的內容(Map)返回;
我們經常遇到的List,通過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的擁有者;
2.GenericArrayType
泛型數組類型,例如E[] 、T[]、List<String>[] (可以理解為包含泛型變量的數組,因為List<String>[] 中的String其實就是泛型)
注意:list[] 、String[]不是該類型,他們不包含泛型,他們直接是特殊的Class類型
GenericArrayType
在GenericArrayType接口中,僅有1個方法,就是getGenericComponentType();
2.1 getGenericComponentType
返回泛型數組中元素的Type類型,即List<String>[] 中的 List<String>(ParameterizedTypeImpl)、T[] 中的T(TypeVariableImpl);
值得注意的是,無論是幾維數組,getGenericComponentType()方法都只會脫去最右邊的[],返回剩下的值;
3.TypeVariable
泛型的類型變量,指的是List、Map中的T,K,V等值,實際的Java類型是TypeVariableImpl(TypeVariable的子類);此外,還可以對類型變量加上extend限定,這樣會有類型變量對應的上限;
TypeVariable
在TypeVariable接口中,有3個方法,分別為getBounds()、getGenericDeclaration()、getName();
3.1 getBounds
獲得該類型變量的上限,也就是泛型中extend右邊的值;例如 List ,Number就是類型變量T的上限;如果我們只是簡單的聲明了List(無顯式定義extends),那么默認為Object;
無顯式定義extends:
值得注意的是,類型變量的上限可以為多個,必須使用&符號相連接,例如 List;其中,& 后必須為接口;
3.2 getGenericDeclaration
獲取聲明該類型變量實體,也就是TypeVariableTest中的TypeVariableTest;
3.3 getName
獲取類型變量在源碼中定義的名稱;
說到TypeVariable類,就不得不提及Java-Type體系中另一個比較重要的接口---GenericDeclaration;含義為:聲明類型變量的所有實體的公共接口;也就是說該接口定義了哪些地方可以定義類型變量(泛型);
通過查看源碼發現,GenericDeclaration下有三個子類,分別為Class、Method、Constructor;也就是說,我們定義泛型只能在一個類中這3個地方自定義泛型;
此時,我們不禁要問,我們不是經常在類中的屬性聲明泛型嗎,怎么Field沒有實現 GenericDeclaration接口呢?
其實,我們在Field中並沒有聲明泛型,而是在使用泛型而已!不信,我們實際上代碼來看看!
1.首先在Class上定義泛型:
Class定義泛型
2.我們沒有在Class上定義泛型,直接在構造方法上定義泛型
泛型構造
3.同樣沒有在Class定義泛型,直接在普通方法上定義泛型
泛型方法
4.我們直接在屬性上定義
屬性上定義泛型
我們看到,如果不在Class上定義,屬性上並不能直接使用!所以,這也是我之前說的屬性上並不是定義泛型,而是使用泛型,所以Field並沒有實現GenericDeclaration接口!
4.Class
Type接口的實現類,是我們工作中常用到的一個對象;在Java中,每個.class文件在程序運行期間,都對應着一個Class對象,這個對象保存有這個類的全部信息;因此,Class對象也稱之為Java反射的基礎;
通過上面的例子,可以看出,當我們沒有聲明泛型的時候,我們普通的對象就是一個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體系中相關對象的介紹;