1挤聘、Type
Type是一個(gè)接口凡辱,是所有類型的父類眉尸,下圖展示了Type的繼承結(jié)構(gòu):
可以看到Type的子類有如下幾個(gè):
- 1、Class:原始類型/基本類型
- 2缘屹、ParameterizedType:參數(shù)化類型凛剥,在聲明含有泛型的變量就是參數(shù)化類型,無(wú)論其中的泛型有沒有具體的實(shí)現(xiàn)轻姿,如List<T> list1犁珠,List<String> list2都是參數(shù)化類型的。
- 3踢代、TypeVariable:類型變量盲憎,其實(shí)代表的就是泛型尖括號(hào)中的東西,比如List<T>中的T胳挎,或者直接聲明一個(gè)泛型變量如private T t饼疙。
- 4、WildcardType:通配符類型
- 5慕爬、GenericArrayType:泛型數(shù)組類型
2窑眯、ParameterizedType:參數(shù)化類型
需要注意的是,并不只是 Collection<String> 才是 parameterized医窿,任何類似于 ClassName<V> 這樣的類型都是 ParameterizedType 磅甩,比如下面的這些都是 parameterizedType.
Map<String, Person> map;
Set<String> set1;
Class<?> clz;
Holder<String> holder;
List<String> list;
而類似于這樣的 ClassName 不是 ParameterizedType。
Set set;
List aList;
T t;
2.1姥卢、ParameterizedType 的幾個(gè)主要方法
- Type[] getActualTypeArguments();
- Type getRawType();
- Type getOwnerType();
1卷要、Type[] getActualTypeArguments()
getActualTypeArguments()
獲取類型內(nèi)部的泛型的實(shí)際類型,如Map<String,Person> map 返回的是String類型和Person類型組成的Type的數(shù)組独榴。
2僧叉、Type getRawType()
getRawType()
返回原始類型,如 Map<String,Person> map返回的就是Map類型
3棺榔、Type getOwnerType()
getOwnerType()
獲取所有者類型瓶堕,只有內(nèi)部類才有所有者,如Map.Entry<String, String> entry 的 getOwnerType() 返回的就是Map類型症歇,而Map<String,String>則返回null郎笆。
2.2、Demo
public class ParameterizedTypeTest {
private Map<String, ParameterizedTypeTest> map;
private Set<String> set1;
private Class<?> clz;
private Holder<String> holder;
private List<String> list;
private ArrayList<String> arrayList;
private Map.Entry<String, String> entry;
private String str;
private Integer i;
private Set set;
private List aList;
static class Holder<V> {
}
public static void main(String[] args) {
Field f = null;
try {
// 拿到所有的字段
Field[] fields = ParameterizedTypeTest.class.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
f = fields[i];
if (f.getGenericType() instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) f.getGenericType();
System.out.println(f.getName() + ":");
System.out.println("\t ParameterizedType:" + Arrays.asList(parameterizedType.getActualTypeArguments()));
System.out.println("\t getRawType:" + parameterizedType.getRawType());
System.out.println("\t getOwnerType:" + parameterizedType.getOwnerType());
}
// 輸出不是ParameterizedType 參數(shù)化類型的
else {
System.out.println(f.getName() + ":is not ParameterizedType ");
}
}
} catch (Exception e) {
}
}
}
輸出:
map:(對(duì)應(yīng)Map<String, ParameterizedTypeTest> map)
ParameterizedType:[class java.lang.String, class com.fsx.maintest.ParameterizedTypeTest]
getRawType:interface java.util.Map
getOwnerType:null
set1:(對(duì)應(yīng)Set<String> set1)
ParameterizedType:[class java.lang.String]
getRawType:interface java.util.Set
getOwnerType:null
clz:(對(duì)應(yīng)Class<?> clz)
ParameterizedType:[?]
getRawType:class java.lang.Class
getOwnerType:null
holder:(對(duì)應(yīng)Holder<String> holder)
ParameterizedType:[class java.lang.String]
getRawType:class com.fsx.maintest.ParameterizedTypeTest$Holder
getOwnerType:class com.fsx.maintest.ParameterizedTypeTest
list:(對(duì)應(yīng)List<String>)
ParameterizedType:[class java.lang.String]
getRawType:interface java.util.List
getOwnerType:null
arrayList:(對(duì)應(yīng)ArrayList<String>)
ParameterizedType:[class java.lang.String]
getRawType:class java.util.ArrayList
getOwnerType:null
entry:(對(duì)應(yīng)Map.Entry<String忘晤,String>)
ParameterizedType:[class java.lang.String, class java.lang.String]
getRawType:interface java.util.Map$Entry
getOwnerType:interface java.util.Map
str:is not ParameterizedType
i:is not ParameterizedType
set:is not ParameterizedType
aList:is not ParameterizedType
2宛蚓、TypeVariable:類型變量
比如 :
public T t,屬于類型變量德频。t屬于類型變量苍息。
public class TypeVariableBean<K extends InputStream & Serializable, V> , K和V都是屬于類型變量壹置。
public <T> test(T t){}方法中的<T>
以及參數(shù)中的T t都屬于類型變量竞思。
2.1、TypeVariable的主要方法
- Type[] getBounds(): 得到上邊界的Type數(shù)組钞护,如K的上邊界數(shù)組是InputStream 和 Serializable 盖喷。V沒有指定的話上邊界是Object。
- D getGenericDeclaration():返回的是聲明該類型變量的實(shí)體难咕,如
TypeVariableBean<K extends InputStream & Serializable, V>
中的TypeVariableBean
课梳。 - String getName();返回的是這個(gè)type variable的名稱。
2.2余佃、Demo
2.2.1暮刃、獲取類的泛型類型
先定義一個(gè)泛型類
public class TestClass<T> {
}
獲取該泛型類的泛型的類型
//獲取類的泛型的類型
TypeVariable<Class<TestClass>>[] classVariable = TestClass.class.getTypeParameters();
for (TypeVariable<Class<TestClass>> classTypeVariable : classVariable) {
Type[] bounds = classTypeVariable.getBounds();
Class<TestClass> genericDeclaration = classTypeVariable.getGenericDeclaration();
String name = classTypeVariable.getName();
System.out.println("上邊界:"+Arrays.toString(bounds));
System.out.println("聲明該類型的實(shí)體:"+genericDeclaration.getName());
System.out.println("名稱:"+name);
}
輸出
上邊界:[class java.lang.Object]
聲明該類型的實(shí)體:com.example.abu.serviceproject.TestClass
名稱:T
2.2.2、獲取類的屬性的泛型類型
在TextClass中聲明一個(gè)類型變量的屬性
public class TestClass<T> {
private T t;
}
獲取屬性的泛型類型
try {
Field field = TestClass.class.getDeclaredField("t");
Type genericType = field.getGenericType();
if (genericType instanceof TypeVariable) {
TypeVariable typeVariable= (TypeVariable) genericType;
Class genericDeclaration = (Class) typeVariable.getGenericDeclaration();
Type[] bounds = typeVariable.getBounds();
String name = typeVariable.getName();
System.out.println("上邊界:"+Arrays.toString(bounds));
System.out.println("聲明該類型的實(shí)體:"+genericDeclaration.getName());
System.out.println("名稱:"+name);
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
輸出
上邊界:[class java.lang.Object]
聲明該類型的實(shí)體:com.example.abu.serviceproject.TestClass
名稱:T
2.2.3爆土、獲取類的方法的泛型類型
在TestClass中創(chuàng)建一個(gè)方法
public class TestClass<T> {
T t;
public <K> void test(T t, K k) {
}
}
可以看到這里我們聲明了一個(gè)泛型方法test()
椭懊,聲明了一個(gè)泛型<K>
,并且接收兩個(gè)參數(shù)T t
和K k
步势,這三個(gè)都是類型變量類型的氧猬,它們有什么區(qū)別呢?
Method[] declaredMethods = TestClass.class.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
//獲取方法定義的泛型類型
TypeVariable<Method>[] typeParameters = declaredMethod.getTypeParameters();
for (TypeVariable<Method> typeParameter : typeParameters) {
Method genericDeclaration = typeParameter.getGenericDeclaration();
Type[] bounds = typeParameter.getBounds();
String name = typeParameter.getName();
System.out.println("方法泛型的名稱:" + name+":");
System.out.println("\t方法泛型的上邊界:" + Arrays.toString(bounds));
System.out.println("\t方法中聲明該類型的實(shí)體:" + genericDeclaration.getName());
}
//獲取方法參數(shù)的泛型類型
Type[] genericParameterTypes = declaredMethod.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
if (genericParameterType instanceof TypeVariable) {
TypeVariable typeVariable = (TypeVariable) genericParameterType;
GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();
Type[] bounds = typeVariable.getBounds();
String name = typeVariable.getName();
System.out.println("方法中參數(shù)泛型的名稱:" + name + ":");
System.out.println("\t方法參數(shù)中泛型的上邊界:" + Arrays.toString(bounds));
if (genericDeclaration instanceof Class)
System.out.println("\t方法中參數(shù)聲明該類型的實(shí)體:" + ((Class) genericDeclaration).getName());
else if (genericDeclaration instanceof Method)
System.out.println("\t方法中參數(shù)聲明該類型的實(shí)體:" + ((Method) genericDeclaration).getName());
}
}
}
輸出
方法泛型的名稱:K:
方法泛型的上邊界:[class java.lang.Object]
方法中聲明該類型的實(shí)體:test
方法中參數(shù)泛型的名稱:T:
方法參數(shù)中泛型的上邊界:[class java.lang.Object]
方法中參數(shù)聲明該類型的實(shí)體:com.example.abu.serviceproject.TestClass
方法中參數(shù)泛型的名稱:K:
方法參數(shù)中泛型的上邊界:[class java.lang.Object]
方法中參數(shù)聲明該類型的實(shí)體:test
我們?cè)?code>class TestClass<T>泛型類中聲明了一個(gè)泛型方法<K> void test(T t, K k)
坏瘩。
-
Method.getTypeParameters()
:返回的是定義在泛型方法上泛型類型的數(shù)組盅抚,對(duì)于泛型方法<K> void test(T t, K k)
來說就是K。由于是泛型是聲明在方法上的所以getGenericDeclaration
返回的就是Method test() -
Method.getGenericParameterTypes()
:返回的是方法中參數(shù)的泛型類型倔矾,test()
方法有T t, K k
兩個(gè)參數(shù)妄均,由于T
是聲明在TestClass
上的,K
是聲明在方法上的,所以對(duì)于T getGenericDeclaration
返回的就是Class TestClass哪自,而對(duì)于K getGenericDeclaration
返回的就是Method test()丰包。
3、GenericArrayType:泛型數(shù)組
GenericArrayType是泛型數(shù)組提陶,組成數(shù)組的元素中有泛型的數(shù)組就是GenericArrayType類型的烫沙,組成數(shù)組的元素可以是ParameterizedType類型的也可以是TypeVariable類型的。
// 屬于 GenericArrayType 組成元素是ParameterizedType
List<String>[] pTypeArray;
// 屬于 GenericArrayType 組成元素是TypeVariable
T[] vTypeArray;
// 不屬于 GenericArrayType
List<String> list;
// 不屬于 GenericArrayType
String[] strings;
// 不屬于 GenericArrayType
Person[] ints;
Demo
public class TestClass<T> {
T[] t;
TestClass<T>[] testClassArray;
List<String>[] listArray;
String[] strArray;
}
獲取類中的屬性是否是泛型數(shù)組類型隙笆,并獲取數(shù)組中元素的類型锌蓄。
public void test() {
Field[] declaredFields = TestClass.class.getDeclaredFields();
for (Field declaredField : declaredFields) {
Type genericType = declaredField.getGenericType();
String fieldName = declaredField.getName();
if (genericType instanceof GenericArrayType) {
System.out.println("泛型數(shù)組:" + fieldName + ":");
GenericArrayType genericArrayType= (GenericArrayType) genericType;
Type genericComponentType = genericArrayType.getGenericComponentType();
System.out.println("\t泛型數(shù)組中元素的類型:"+genericComponentType);
} else {
System.out.println("非泛型數(shù)組:" + fieldName);
}
}
}
輸出
泛型數(shù)組:t: (對(duì)應(yīng)T[] t)
泛型數(shù)組中元素的類型:T
泛型數(shù)組:testClassArray:(對(duì)應(yīng)TestClass<T>[] testClassArray)
泛型數(shù)組中元素的類型:com.example.abu.serviceproject.TestClass<T>
泛型數(shù)組:listArray:(對(duì)應(yīng)List<String>[] listArray)
泛型數(shù)組中元素的類型:java.util.List<java.lang.String>
非泛型數(shù)組:(對(duì)應(yīng)String[] strArray)strArray
4、WildcardType :通配符類型
<?>撑柔、<瘸爽?extends Number>、<? super Integer>
這些都是通配符類型的铅忿,extends 用來指定上邊界剪决,沒有指定的話上邊界默認(rèn)是 Object, super 用來指定下邊界,沒有指定的話為 null柑潦。
幾個(gè)主要方法介紹
- Type[] getLowerBounds() 得到上邊界 Type 的數(shù)組
- Type[] getUpperBounds() 得到下邊界 Type 的數(shù)組
下面一起來看一下例子享言。
public class WildcardTypeBean<T> {
private List<? extends Number> a; // a沒有下界,
// 沒有指定的話,上邊界默認(rèn)是 Object ,下邊界是 String
private List<? super String> b;
private List<String> c;
private List<T> list;
private Class<?> aClass;
}
public void testWildCardType() {
Field[] fields = WildcardTypeBean.class.getDeclaredFields();
for (Field field : fields) {
Type genericType = field.getGenericType();
if (genericType instanceof WildcardType)
System.out.println(field.getName() + " is WildcardType");
else if (genericType instanceof ParameterizedType){
System.out.println(field.getName() + " is ParameterizedType");
ParameterizedType parameterizedType= (ParameterizedType) genericType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
Type actualTypeArgument=actualTypeArguments[0];
if(actualTypeArgument instanceof WildcardType){
WildcardType wildcardType= (WildcardType) actualTypeArgument;
System.out.println("-----------------通配符類型-----------------");
System.out.println("name:"+wildcardType.getTypeName());
System.out.println("上邊界:"+Arrays.toString(wildcardType.getUpperBounds()));
System.out.println("下邊界:"+Arrays.toString(wildcardType.getLowerBounds()));
}else if(actualTypeArgument instanceof ParameterizedType){
System.out.println("-----------------參數(shù)化類型-----------------");
System.out.println("name:"+actualTypeArgument.getTypeName());
}else if(actualTypeArgument instanceof TypeVariable){
System.out.println("-----------------類型變量-----------------");
System.out.println("name:"+actualTypeArgument.getTypeName());
}else if(actualTypeArgument instanceof Class){
System.out.println("-----------------原始類型-----------------");
System.out.println("name:"+actualTypeArgument.getTypeName());
}
}
}
}
輸出
a is ParameterizedType
-----------------通配符類型-----------------
name:? extends java.lang.Number
上邊界:[class java.lang.Number]
下邊界:[]
b is ParameterizedType
-----------------通配符類型-----------------
name:? super java.lang.String
上邊界:[class java.lang.Object]
下邊界:[class java.lang.String]
c is ParameterizedType
-----------------原始類型-----------------
name:java.lang.String
list is ParameterizedType
-----------------類型變量-----------------
name:T
aClass is ParameterizedType
-----------------通配符類型-----------------
name:?
上邊界:[class java.lang.Object]
下邊界:[]