Type 接口【重要】
Type接口完整的定義:
public interface java.lang.reflect.Type {
/**
* Returns a string describing this type, including information about any type parameters.
* @implSpec The default implementation calls {@code toString}.
* @return a string describing this type
* @since 1.8
*/
default String getTypeName() {
return toString();
}
}
所有已知子接口:GenericArrayType, ParameterizedType, TypeVariable<D>, WildcardType
所有已知實現類:Class
Type is the common superinterface for all types in the Java programming language. These include raw types, parameterized types, array types, type variables and primitive types.
Type 是 Java 編程語言中
【所有類型】的公共高級接口。它們包括
原始類型、參數化類型(泛型)、數組類型、類型變量和基本類型。
注意區分Type與Class的區別,這里的
Class是Type的一種,而像數組、枚舉等"類型"是相對於Class來說的。
Type接口的來歷
我們知道,Type是JDK5開始引入的,其引入主要是為了
泛型,沒有泛型的之前,只有所謂的
原始類型。此時,所有的原始類型都通過字節碼文件類Class類進行抽象。Class類的一個具體對象就代表一個指定的原始類型。
泛型出現之后,也就擴充了數據類型。從只有原始類型擴充了參數化類型、類型變量類型、泛型數組類型,也就是Type的子接口。
那為什么沒有統一到Class下,而是增加一個Type呢?(Class也是種類的意思,Type是類型的意思)
是
為了程序的擴展性,最終引入了Type接口作為Class,ParameterizedType,GenericArrayType,TypeVariable和WildcardType這幾種類型的總的父接口。這樣實現了Type類型參數接受以上五種子類的實參或者返回值類型就是Type類型的參數。
Java中的所有類型
對於這篇筆記,只需搞清楚這里就差不多了:
- raw type:原始類型,對應Class 。這里的Class不僅僅指平常所指的類,還包括數組、接口、注解、枚舉等結構。
- primitive types:基本類型,仍然對應Class
- parameterized types:參數化類型,對應ParameterizedType,帶有類型參數的類型,即常說的泛型,如:List<T>、Map<Integer, String>、List<? extends Number>。
- type variables:類型變量,對應TypeVariable<D>,如參數化類型中的E、K等類型變量,表示泛指任何類。
- array types:(泛型)數組類型,對應GenericArrayType,比如List<T>[],T[]這種。注意,這不是我們說的一般數組,而是表示一種【元素類型是參數化類型或者類型變量的】數組類型。
測試代碼
public class Test {
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
Method method = Test.class.getMethod("testType", List.class, List.class, List.class, List.class, List.class, Map.class);
Type[] types = method.getGenericParameterTypes();//按照聲明順序返回 Type 對象的數組
for (Type type : types) {
ParameterizedType pType = (ParameterizedType) type;//最外層都是ParameterizedType
Type[] types2 = pType.getActualTypeArguments();//返回表示此類型【實際類型參數】的 Type 對象的數組
for (int i = 0; i < types2.length; i++) {
Type type2 = types2[i];
System.out.println(i + " 類型【" + type2 + "】\t類型接口【" + type2.getClass().getInterfaces()[0].getSimpleName() + "】");
}
}
}
public <T> void testType(List<String> a1, List<ArrayList<String>> a2, List<T> a3, //
List<? extends Number> a4, List<ArrayList<String>[]> a5, Map<String, Integer> a6) {
}
}
運行結果
0 類型【class java.lang.String】 類型接口【Serializable】
0 類型【java.util.ArrayList<java.lang.String>】 類型接口【ParameterizedType】
0 類型【T】 類型接口【TypeVariable】
0 類型【? extends java.lang.Number】 類型接口【WildcardType】
0 類型【java.util.ArrayList<java.lang.String>[]】 類型接口【GenericArrayType】
0 類型【class java.lang.String】 類型接口【Serializable】
1 類型【class java.lang.Integer】 類型接口【Serializable】
Type 接口的四個子接口
ParameterizedType 泛型/參數化類型【重要】
public interface java.lang.reflect.ParameterizedType extends Type
ParameterizedType 表示
參數化類型,
帶有類型參數的類型,即常說的泛型,如:List<T>、Map<Integer, String>、List<? extends Number>。
方法
- Type[] getActualTypeArguments() 返回表示此類型實際類型參數的 Type 對象的數組。【重要】
- 簡單來說就是:獲得參數化類型中<>里的類型參數的類型。
- 因為可能有多個類型參數,例如Map<K, V>,所以返回的是一個Type[]數組。
- 注意:無論<>中有幾層<>嵌套,這個方法僅僅脫去最外層的<>,之后剩下的內容就作為這個方法的返回值,所以其返回值類型不一定。
- Type getOwnerType() 返回 Type 對象,表示此類型是其成員之一的類型。
- 如果此類型為頂層類型,則返回 null(大多數情況都是這樣)。
- Type getRawType() 返回 Type 對象,表示聲明此類型的類或接口。
- 簡單來說就是:返回最外層<>前面那個類型,例如Map<K ,V>,返回的是Map類型。
public class Test {
public static void main(String[] args) throws Exception {
Method method = Test.class.getMethod("test", Map.Entry.class);
Type[] types = method.getGenericParameterTypes();
for (Type type : types) {
ParameterizedType pType = (ParameterizedType) type;
System.out.println(pType + " ★ " + pType.getOwnerType() + " ★ " + pType.getRawType() //
+ " ★ " + Arrays.toString(pType.getActualTypeArguments()));
//java.util.Map.java.util.Map$Entry<T, U> ★ interface java.util.Map ★ interface java.util.Map$Entry ★ [T, U]
}
}
public static <T, U> void test(Map.Entry<T, U> mapEntry) {
}
}
TypeVariable<D> 類型變量/泛指任何類【掌握】
public interface java.lang.reflect.TypeVariable<D extends GenericDeclaration> extends Type
類型變量,如參數化類型中的E、K等類型變量,表示泛指任何類。
方法
- Type[] getBounds() 返回表示此類型變量上邊界的 Type 對象的數組。
- 返回:表示此類型變量的上邊界的 Type 的數組
- 注意,如果未顯式聲明上邊界,則上邊界為 Object。
- D getGenericDeclaration() 返回 GenericDeclaration 對象,該對象表示聲明此類型變量的一般聲明。
- 返回:為此類型變量聲明的一般聲明。
- String getName() 返回此類型變量的名稱,它出現在源代碼中。
public static <T extends Person, U> void main(String[] args) throws Exception {
Method method = Test.class.getMethod("main", String[].class);
TypeVariable<?>[] tvs = method.getTypeParameters();//返回聲明順序的 TypeVariable 對象的數組
System.out.println("聲明的類型變量有:" + Arrays.toString(tvs));//[T, U]
for (int i = 0; i < tvs.length; i++) {
GenericDeclaration gd = tvs[i].getGenericDeclaration();
System.out.println("【GenericDeclaration】" + gd);//public static void com.bqt.Test.main(java.lang.String[]) throws java.lang.Exception
System.out.println(gd.getTypeParameters()[i] == tvs[i]);//true。 GenericDeclaration和TypeVariable兩者相互持有對方的引用
System.out.println(tvs[i] + " " + tvs[i].getName() + " " + Arrays.toString(tvs[i].getBounds()));//T T [class com.bqt.Person] 和 U U [class java.lang.Object]
}
}
GenericArrayType (泛型)數組類型
public interface java.lang.reflect.GenericArrayType extends Type
GenericArrayType 表示一種
(泛型)數組類型,其組件類型為參數化類型或類型變量。
比如List<T>[],T[]這種。注意,這不是我們說的一般數組,而是表示一種【元素類型是參數化類型或者類型變量的】數組類型。
方法
- Type getGenericComponentType() 返回表示此數組的組件類型的 Type 對象。此方法創建數組的組件類型。
- 獲取泛型數組中元素的類型,要注意的是:無論從左向右有幾個[]並列,這個方法僅僅脫去最右邊的[]之后剩下的內容就作為這個方法的返回值。
WildcardType 通配符(泛型)表達式
public interface java.lang.reflect.WildcardType extends Type
WildcardType代表通配符表達式,或泛型表達式,比如【?】【? super T】【? extends T】。
雖然WildcardType是Type的一個子接口,但並不是Java類型中的一種。
方法
- Type[] getLowerBounds() 返回表示此類型變量下邊界的 Type 對象的數組。注意,如果不存在顯式聲明的下邊界,則下邊界為類型 null。在此情況下,將返回長度為零的數組。
- Type[] getUpperBounds() 返回表示此類型變量上邊界的 Type 對象的數組。注意,如果不存在顯式聲明的上邊界,則上邊界為 Object。