前言
Type體系的引入是對(duì)泛型的一種補(bǔ)償。java泛型的引入為編譯器提供了更嚴(yán)格的代碼審查樟蠕,但這些泛型信息在運(yùn)行時(shí)將會(huì)被擦除,這將導(dǎo)致程序在運(yùn)行期間無法獲取到屬性或者類的具體聲明靠柑。Type的引入使得開發(fā)者在程序運(yùn)行期內(nèi)獲取屬性或者類的具體聲明成為可能寨辩。
Type是一個(gè)接口,它的實(shí)現(xiàn)類如下圖所示:
從上圖可以看出歼冰,Class類是繼承了Type接口的靡狞,而Class類在反射中應(yīng)用廣泛,因此這很容易讓我們想到Type的大多數(shù)應(yīng)用應(yīng)該也是在反射中隔嫡。接下來看幾個(gè)常見的實(shí)現(xiàn)接口甸怕。
ParameterizedType(參數(shù)化類型)
帶有泛型參數(shù)的屬性聲明都屬于ParameterizedType甘穿,帶有泛型參數(shù)的方法返回值類型也屬于ParameterizedType
public class A {
//這幾個(gè)屬性都帶泛型參數(shù),因此都屬于ParameterizedType
private List<String> list;
private Map<String, Integer> map;
private Class<?> aClass;
private Bean<String> bean;
//該返回值類型屬于ParameterizedType
public List<String> getList() {
return null;
}
}
主要方法名 | 說明 |
---|---|
Type[] getActualTypeArguments(); | 返回這個(gè) ParameterizedType 類型的參數(shù)的實(shí)際類型(即泛型)數(shù)組梢杭。 如 Map<String,Integer> map 這個(gè) ParameterizedType 返回: [class java.lang.String, class java.lang.Integer]温兼。 |
Type getRawType(); | 返回的是當(dāng)前這個(gè) ParameterizedType 的類型的原型,如 Map<String,Integer> map 這個(gè)返回:interface java.util.Map |
Type getOwnerType(); | 當(dāng)這個(gè)變量類型為某個(gè)類的內(nèi)部類并在聲明時(shí)加入了泛型武契,這個(gè)方法返回其父類的Type募判。否者返回null |
測試代碼
##定義類
public class A {
private List<String> list;
private Map<String, Integer> map;
private Class<?> aClass;
private Bean<String> bean;
public class Bean<T> {
}
}
##測試代碼
@Test
public void test() throws IOException {
Class c = A.class;
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
System.out.println(field.getName());
Type type = field.getGenericType();
if (type instanceof ParameterizedType) {
System.out.println(Arrays.toString(((ParameterizedType) type).getActualTypeArguments()));
System.out.println(((ParameterizedType) type).getRawType());
System.out.println(((ParameterizedType) type).getOwnerType());
}
System.out.println("====================================");
}
}
##輸出
list
[class java.lang.String]
interface java.util.List
null
====================================
map
[class java.lang.String, class java.lang.Integer]
interface java.util.Map
null
====================================
aClass
[?]
class java.lang.Class
null
====================================
bean
[class java.lang.String]
class com.lu.test.A$Bean
class com.lu.test.A
====================================
TypeVariable
在類或者接口聲明的時(shí)候添加泛型,那么這個(gè)類的泛型就屬于TypeVariable
//A類聲明了2個(gè)泛型咒唆,即兩個(gè)TypeVariable
public class A<T extends String, E>
主要方法 | 說明 |
---|---|
Type[] getBounds(); | 如果聲明的泛型使用了extends 那么返回繼承和實(shí)現(xiàn)的類和接口届垫,例如泛型聲明<T extends String&Serializable> 所對(duì)應(yīng)的getBounds()返回:[class java.lang.String, interface java.io.Serializable] |
D getGenericDeclaration(); | 返回聲明改TypeVariable (即泛型)的類,例如上述代碼返回的就是A類的GenericDeclaration全释; |
##聲明類
public class A<T extends String & Serializable, E> {
}
##測試代碼
@Test
public void test() throws IOException {
Class c = A.class;
Type[] types = c.getTypeParameters();
for (Type type : types) {
System.out.println(type.getTypeName());
if (type instanceof TypeVariable) {
System.out.println(((TypeVariable) type).getGenericDeclaration());
System.out.println(Arrays.toString(((TypeVariable) type).getBounds()));
}
System.out.println("==========================================");
}
}
##輸出結(jié)果
T
class com.lu.test.A
[class java.lang.String, interface java.io.Serializable]
==========================================
E
class com.lu.test.A
[class java.lang.Object]
==========================================
GenericArrayType
范型數(shù)組,組成數(shù)組的元素中有范型 則屬于GenericArrayType
public class A<T> {
T[] ts;//屬于GenericArrayType
List<String>[] lists;//屬于GenericArrayType
private String[] arr;
}
主要方法 | 說明 |
---|---|
Type getGenericComponentType(); | 返回改數(shù)組類型元素的類型装处,例如T[] 返回的是T |
##聲明類
public class A<T> {
T[] ts;
List<String>[] lists;
}
##測試類
@Test
public void test() throws IOException {
Class c = A.class;
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
Type type = field.getGenericType();
if (type instanceof GenericArrayType) {
System.out.println(((GenericArrayType) type).getGenericComponentType());
}
System.out.println("==================================");
}
}
##輸出結(jié)果
T
==================================
java.util.List<java.lang.String>
==================================
WildcardType 通配符的類型
形如<?> <? extends String> <? super Integer> 中的泛型(其實(shí)就是就是“?”)類型就屬于WildcardType
public class A {
List<? extends String> ts;//屬于WildcardType
List<?> list;//屬于WildcardType
List<? super Integer> ins;//屬于WildcardType
}
主要方法 | 說明 |
---|---|
Type[] getUpperBounds(); | 如果有extends 則返回的是extends對(duì)象的type 否則是[object] |
Type[] getLowerBounds(); | 如果有super 則返回的是super 對(duì)象的type 否則是[] |
##聲明類
public class A {
List<? extends String> ts;
List<?> list;
List<? super Integer> ins;
}
##測試
@Test
public void test() throws IOException {
Class c = A.class;
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
ParameterizedType type = (ParameterizedType) field.getGenericType();
for (Type type1 : type.getActualTypeArguments()) {
System.out.println("getTypeName(): " + type1.getTypeName());
if (type1 instanceof WildcardType) {
System.out.println("getUpperBounds(): " + Arrays.toString(((WildcardType) type1).getUpperBounds()));
System.out.println("getLowerBounds(): " + Arrays.toString(((WildcardType) type1).getLowerBounds()));
System.out.println("===========================");
}
}
}
}
##輸出結(jié)果
getTypeName(): ? extends java.lang.String
getUpperBounds(): [class java.lang.String]
getLowerBounds(): []
===========================
getTypeName(): ?
getUpperBounds(): [class java.lang.Object]
getLowerBounds(): []
===========================
getTypeName(): ? super java.lang.Integer
getUpperBounds(): [class java.lang.Object]
getLowerBounds(): [class java.lang.Integer]
===========================
注意點(diǎn)
上面介紹了四個(gè)比較常見的Type實(shí)現(xiàn)接口浸船,它們在用法上有很大的區(qū)別妄迁。在區(qū)分的時(shí)候比較繁瑣。不過大體上來說糟袁, ParameterizedType和GenericArrayType所修飾的是屬性本身的類型判族,例如變量類型,方法返回值類型项戴。而TypeVariable 和WildcardType 所修飾的是泛型類型形帮,例如T,E或者周叮?等辩撑。這一點(diǎn)一定要清楚。
理解Type對(duì)于很多帶泛型編程的框架的深入研究很有幫助仿耽,例如Retrofit合冀,springMvc等框架都適用了Type來解析返回值