上一篇幕侠,提到了Java-Type體系谦去,對Type類型進行了簡單的講解;本篇薄声,就用代碼的方式王悍,對其中的5大類型:原始類型(Class)破镰、參數(shù)化類型(ParameterizedType)、數(shù)組類型(GenericArrayType)压储、類型變量(TypeVariable)鲜漩、基本類型(Class) 進一步說明;
1.ParameterizedType
ParameterizedType表示參數(shù)化類型渠脉,也就是泛型宇整,例如List<T>、Set<T>等芋膘;
在ParameterizedType接口中鳞青,有3個方法,分別是getActualTypeArguments()为朋、 getRawType()臂拓、 getOwnerType();
1.1 getActualTypeArguments
獲取泛型中的實際類型,可能會存在多個泛型习寸,例如Map<K,V>,所以會返回Type[]數(shù)組胶惰;
值得注意的是,無論<>中有幾層嵌套(List<Map<String,Integer>)霞溪,getActualTypeArguments()方法永遠都是脫去最外層的<>(也就是List<>)孵滞,將口號內(nèi)的內(nèi)容(Map<String,Integer>)返回中捆;
我們經(jīng)常遇到的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注釋)
通過注解,我們得知孤页,“擁有者”表示的含義--內(nèi)部類的“父類”尔苦,通過getOwnerType()方法可以獲取到內(nèi)部類的“擁有者”;例如: Map? 就是 Map.Entry<String,String>的擁有者散庶;
2.GenericArrayType
泛型數(shù)組類型蕉堰,例如List<String>[] 、T[]等悲龟;
在GenericArrayType接口中,僅有1個方法冰寻,就是getGenericComponentType()须教;
2.1 getGenericComponentType
返回泛型數(shù)組中元素的Type類型,即List<String>[] 中的 List<String>(ParameterizedTypeImpl)斩芭、T[] 中的T(TypeVariableImpl)轻腺;
值得注意的是,無論是幾維數(shù)組划乖,getGenericComponentType()方法都只會脫去最右邊的[]贬养,返回剩下的值;
3.TypeVariable
泛型的類型變量琴庵,指的是List<T>误算、Map<K,V>中的T,K迷殿,V等值儿礼,實際的Java類型是TypeVariableImpl(TypeVariable的子類);此外庆寺,還可以對類型變量加上extend限定蚊夫,這樣會有類型變量對應(yīng)的上限;
在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;含義為:聲明類型變量的所有實體的公共接口士复;也就是說該接口定義了哪些地方可以定義類型變量(泛型)图谷;
通過查看源碼發(fā)現(xiàn),GenericDeclaration下有三個子類阱洪,分別為Class便贵、Method、Constructor冗荸;也就是說承璃,我們定義泛型只能在一個類中這3個地方自定義泛型;
此時蚌本,我們不禁要問盔粹,我們不是經(jīng)常在類中的屬性聲明泛型嗎,怎么Field沒有實現(xiàn) GenericDeclaration接口呢魂毁?
其實玻佩,我們在Field中并沒有聲明泛型,而是在使用泛型而已席楚!不信咬崔,我們實際上代碼來看看!
1.首先在Class上定義泛型:
2.我們沒有在Class上定義泛型,直接在構(gòu)造方法上定義泛型
3.同樣沒有在Class定義泛型垮斯,直接在普通方法上定義泛型
3.我們直接在屬性上定義
我們看到郎仆,如果不在Class上定義,屬性上并不能直接使用兜蠕!所以扰肌,這也是我之前說的屬性上并不是定義泛型,而是使用泛型熊杨,所以Field并沒有實現(xiàn)GenericDeclaration接口曙旭!
4.Class
Type接口的實現(xiàn)類,是我們工作中常用到的一個對象晶府;在Java中桂躏,每個.class文件在程序運行期間,都對應(yīng)著一個Class對象川陆,這個對象保存有這個類的全部信息剂习;因此,Class對象也稱之為Java反射的基礎(chǔ)较沪;
通過上面的例子鳞绕,可以看出,當我們沒有聲明泛型的時候尸曼,我們普通的對象就是一個Class類型们何,是Type中的一種;
5.WildcardType
骡苞?---通配符表達式垂蜗,表示通配符泛型,但是WildcardType并不屬于Java-Type中的一鐘解幽;例如:List<? extends Number> 和 List<? super Integer>;
在WildcardType接口中烘苹,有2個方法躲株,分別為getUpperBounds()、getLowerBounds();
5.1 getUpperBounds
獲取泛型變量的上邊界(extends)
5.2 getLowerBounds
獲取泛型變量的下邊界(super)
以上镣衡,就是對Java-Type體系中相關(guān)對象的介紹霜定;