【Type】類型 ParameterizedType


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[]這種。注意,這不是我們說的一般數組,而是表示一種【元素類型是參數化類型者類型變量的】數組類型。
注意:WildcardType代表通配符表達式,或泛型表達式,比如【?】【? super T】【? extends T】。雖然WildcardType是Type的一個子接口,但並不是Java類型中的一種

測試代碼

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。





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM