JDK 1.5 引入 Type,主要是爲了泛型,沒有泛型的以前,只有所謂的原始類型。此時,全部的原始類型都經過字節碼文件類 Class 類進行抽象。Class 類的一個具體對象就表明一個指定的原始類型。java
泛型出現後擴充了數據類型,從只有原始類型擴充了參數化類型、類型變量類型、泛型數組類型。Type 的子接口有:ParameterizedType、TypeVariable、GenericArrayType、WildcardType,實現類有 Class。git
Type 體系中類型的包括:原始類型(Class)、基本類型(Class)、類型變量(TypeVariable)、參數化類型(ParameterizedType)、數組類型(GenericArrayType)。github
// 1. 原始類型(Class) Set set; List aList; String[] arr; // 2. 參數化類型(ParameterizedType) Map<String, Person> map; Set<String> set; Class<?> clazz; List<String> list; // 3. 類型變量(TypeVariable) T t; // 4. 數組類型(GenericArrayType) Class<?>[] clazz; Map<String, Person>[] clazz;
ParameterizedType,參數化類型,形如:Object<T, K>,即常說的泛型,是 Type 的子接口。spring
public interface ParameterizedType extends Type { // 1. 得到<>中實際類型 Type[] getActualTypeArguments(); // 2. 得到 <> 前面實際類型 Type getRawType(); // 3. 若是這個類型是某個類型所屬,得到這個全部者類型,不然返回 null Type getOwnerType(); }
(1) getActualTypeArguments數組
返回這個 Type 類型的參數的實際類型數組,即 <> 裏的類型參數的類型,由於可能有多個類型參數,例如 Map<K, V>,因此返回的是一個 Type[] 數組。.net
【注意】不管 <> 中有幾層 <> 嵌套,這個方法僅僅脫去最外層的 <>,以後剩下的內容就做爲這個方法的返回值,因此其返回值類型不必定。code
public class ParameterizedTypeTest<T> { List<Set> a1; // 返回 Set,Class 類型 List<Set<String>> a2; // 返回 Set<String>,ParameterizedType 類型 List<T> a3; // 返回 T,TypeVariable 類型 List<? extends Set> a4; // 返回 WildcardType 類型 List<Set<String>[]> a5; // 返回 GenericArrayType 類型 @Test public void test1() throws Exception { Method method = getClass().getMethod("test", List.class); Type[] types = method.getGenericParameterTypes(); ParameterizedType pType = (ParameterizedType) types[0]; Type[] type = pType.getActualTypeArguments(); // sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl System.out.println(type[0].getClass().getName()); } public void test(List<ArrayList<String>[]> a) { } }
(2) getRawType對象
返回的是當前這個 ParameterizedType 的類型,即最外層 <> 前面那個類型,如 Map<K ,V> 的 Mapblog
Map.Entry<String, Integer> me; @Test public void rawTypeTest() throws Exception { Field field = getClass().getDeclaredField("me"); ParameterizedType type = (ParameterizedType) field.getGenericType(); // java.util.Map$Entry System.out.println(type.getRawType()); }
(3) getOwnerType接口
返回的是這個 ParameterizedType 所在的類的 Type。
Map.Entry<String, Integer> me; @Test public void ownerTypeTest() throws Exception { Field field = getClass().getDeclaredField("me"); ParameterizedType type = (ParameterizedType) field.getGenericType(); // java.util.Map System.out.println(type.getOwnerType()); }
TypeVariable 描述所謂範型變量,也就是
public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement { // 變量上邊界數組,沒有指定的話是 Object Type[] getBounds(); // 獲取變量被定義在什麼 GenericDeclaration 上 D getGenericDeclaration(); // 獲取變量名字 String getName(); // jdk 1.8 AnnotatedType[] getAnnotatedBounds(); }
getBounds
獲得上邊界的 Type 數組,如 K 的上邊界數組是 InputStream 和 Serializable。V 沒有指定的話,上邊界是 ObjectgetGenericDeclaration
返回的是聲明這個 Type 所在的類 的 TypegetName
返回的是這個 type variable 的名稱(1) getBounds
獲取泛型變量的上邊界的 Type 數組,若是沒有指定則是 Object。
@Test public void test() { // 1. 獲取類上聲明的泛型變量 getTypeParameters TypeVariable<Class<TypeVariable>> typeVariable = TypeVariable.class.getTypeParameters()[0]; // 2. 獲取泛型變量的上邊界 java.lang.reflect.GenericDeclaration System.out.println(Arrays.toString(typeVariable.getBounds())); }
(2) getGenericDeclaration
GenericDeclaration 該接口用來定義哪些對象上是能夠聲明範型變量,目前實現 GenericDeclaration 接口的類包括 Class、Method、Constructor,也就是說只能在這幾種對象上進行範型變量的聲明(定義)。
public class TypeVariableTest<E> { @Test public void getGenericDeclarationTest() { // 1. 類上聲明泛型 TypeVariable<Class<TypeVariableTest>> classType = TypeVariableTest.class.getTypeParameters()[0]; Class<TypeVariableTest> clazzDeclaration = classType.getGenericDeclaration(); // class com.github.binarylei.spring01.day0728.test.TypeVariableTest System.out.println(clazzDeclaration); // 2. 方法上聲明泛型 Method[] methods = TypeVariableTest.class.getMethods(); Method method = Arrays.stream(methods) .filter(m -> m.getName().equals("test")) .collect(Collectors.toList()) .get(0); TypeVariable methodType = (TypeVariable) method.getGenericParameterTypes()[0]; GenericDeclaration methodDeclaration = methodType.getGenericDeclaration(); // public void com.github.binarylei.TypeVariableTest.test(java.lang.Object) System.out.println(methodDeclaration); // 3. 構造器上聲明泛型 } public <T> void test(T t) { } }
範型數組,組成數組的元素中有範型則實現了該接口;它的組成元素是 ParameterizedType 或 TypeVariable 類型
public interface GenericArrayType extends Type { // 得到這個數組元素類型,即得到:A<T>(A<T>[])或T(T[]) Type getGenericComponentType(); }
下面咱們一塊兒來看一下例子:
classA<K>[][] key; Type type = Main.class.getDeclaredField("key").getGenericType(); // com.github.binarylei..classA<K>[] System.out.println(((GenericArrayType)type).getGenericComponentType());
WildcardType,通配符表達式,Type 子接口,可是在 Java 中並無 WildcardType 類型。extends 用來指定上邊界,沒有指定的話上邊界默認是 Object,super 用來指定下邊界,沒有指定的話爲 null。
幾個主要方法介紹:
public interface WildcardType extends Type { Type[] getUpperBounds(); Type[] getLowerBounds(); }
getLowerBounds
獲得上邊界 Type 的數組
getUpperBounds
獲得下邊界 Type 的數組
下面一塊兒來看一下例子:
public class WildcardTypeTest { // 指定上界 Number,下邊界默認爲 [] private List<? extends Number> a; // 指定下界 String,上邊界默認是 Object private List<? super String> b; // 上界和下界都不指定,上邊界默認是 Object,下邊界默認爲 [] private Class<?> clazz; // 沒有通配符,不是 WildcardType private List<String> c; @Test public void test() throws Exception { Field[] fields = WildcardTypeTest.class.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; Type type = field.getGenericType(); String nameString = field.getName(); //1. 先拿到範型類型 if (!(type instanceof ParameterizedType)) { continue; } //2. 再從範型裏拿到通配符類型 ParameterizedType parameterizedType = (ParameterizedType) type; type = parameterizedType.getActualTypeArguments()[0]; if (!(type instanceof WildcardType)) { continue; } System.out.println("-------------" + nameString + "--------------"); WildcardType wildcardType = (WildcardType) type; Type[] lowerTypes = wildcardType.getLowerBounds(); if (lowerTypes != null) { System.out.println("下邊界:" + Arrays.toString(lowerTypes)); } Type[] upTypes = wildcardType.getUpperBounds(); if (upTypes != null) { System.out.println("上邊界:" + Arrays.toString(upTypes)); } } } }
GenericDeclaration 該接口用來定義哪些對象上是能夠聲明範型變量,目前實現 GenericDeclaration 接口的類包括 Class、Method、Constructor,也就是說只能在這幾種對象上進行範型變量的聲明(定義)。
GenericDeclaration 的接口方法 getTypeParameters 用來逐個獲取該 GenericDeclaration 的範型變量聲明。
public interface GenericDeclaration extends AnnotatedElement { // 用來獲取該GenericDeclaration的範型變量聲明 public TypeVariable<?>[] getTypeParameters(); }
(1) 泛型的聲明
//1. 在類(Class)上聲明 class A<T> { T a; } // 2. 在方法上聲明 // 類型變量聲明不是在參數裏邊,並且必須在返回值以前,static 等修飾後 public <E> void test(E e) {} // 3. 在構造器上聲明 public <K> A(K k) {}
【注意】類型變量聲明(定義)的時候不能有下限(既不能有 super),不然編譯報錯。爲何?T extends classA 表示泛型有上限 classA,固然能夠,由於這樣,每個傳進來的類型一定是 classA(具備 classA 的一切屬性和方法),但如果 T super classA,傳進來的類型不必定具備 classA 的屬性和方法,固然就不適用於泛型,說的具體點:
class A<T super classA>{ T t; public void test(){ // t 的子類是 classA,咱們仍是不知道 t 究竟是什麼類型,不知道 t 有那些方法 } }
參考:
天天用心記錄一點點。內容也許不重要,但習慣很重要!