一、簡介
??TypeParameterResolver 是一個(gè)類型參數(shù)解析器,即JavaBean中可能帶泛型如 List<T>、通配符如 <? super SubClass>,而且可能復(fù)雜的繼承關(guān)系,為了獲取到運(yùn)行時(shí)正確具體的類型(包括屬性類型、方法參數(shù)類型、方法返回值類型),需要使用本類解析類型參數(shù),對外暴露的解析屬性、方法參數(shù)類型、方法返回值類型對應(yīng)的方法分別為 #resolveFieldType()、#resolveParamTypes()、#resolveReturnType()。
二、Type 的基礎(chǔ)背景知識
??Type 翻譯成中文是類型,Class 是類,平時(shí)我們接觸比較多的是 Class,那這兩者有什么關(guān)系?其實(shí) Type 是一個(gè)接口,Class 是它的實(shí)現(xiàn)類!那 Type 還有其他繼承的子接口或?qū)崿F(xiàn)類嗎?答案是有,并且各種類型對應(yīng)不同形式的泛型比如 T、Set<T>、T[]、<? super Xxx>,Type 跟泛型息息相關(guān),它有四個(gè)子接口和一個(gè)實(shí)現(xiàn)類,類圖如下:

- 1、
Class:比較常見,表示一個(gè)原始類型,每個(gè)類或接口都有對應(yīng)的 Class 對象,數(shù)組也有對應(yīng)的 Class 對象,所有元素類型相同且維度相同的數(shù)組都共享同一個(gè) Class 對象。 - 2、
ParameterizedType:參數(shù)化類型,形如 Set<String>、Map<String, Object> 這種帶泛型的類型都是參數(shù)化類型。ParameterizedType 是一個(gè)接口,定義了三個(gè)方法,分別為:-
Type[] getActualTypeArguments():獲取參數(shù)化類型的類型變量或是實(shí)際類型列表。比如 Map<String, Object> 的實(shí)際泛型列表為 [String, Object],當(dāng)然實(shí)際使用中還存在嵌套的情況,比如 Map<String, List<User>>,這時(shí)要解析到 value 中嵌套的具體類型,還得對 List<User> 再做解析,所以 TypeParameterResolver 中的實(shí)現(xiàn)帶有遞歸調(diào)用。 -
Type getRawType():獲取參數(shù)話類型中的原始類型。比如 Map<String, Object> 的原始類型為 Map。 -
Type getOwnerType():返回類型所屬的類型。一般的類是在一個(gè)單獨(dú)的類文件中定義的,可視為頂層類型,不為其他類型所有,所以返回 null;如果類型是一個(gè)內(nèi)部類,則返回類型為定義該類的類型,如 Map.Entry<K, V> 是在 Map<K, V> 中定義的,所以其所屬的類型為 Map<K, V>。
-
??代碼演示:
public class ParameterizedTypeTest {
Map<String, Integer> map = new HashMap<String, Integer>();
public static void test(Type type) {
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type[] typeArgs = parameterizedType.getActualTypeArguments();
for (Type typeArg : typeArgs) {
System.out.println(typeArg);
}
System.out.println("RawType: " + parameterizedType.getRawType());
System.out.println("OwnerType: " + parameterizedType.getOwnerType());
} else {
System.out.println("type is not ParameterizedType");
}
}
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
ParameterizedTypeTest obj = new ParameterizedTypeTest();
Type type = obj.getClass().getDeclaredField("map").getGenericType();
test(type);
}
}
??執(zhí)行結(jié)果:
class java.lang.String
class java.lang.Integer
RawType: interface java.util.Map
OwnerType: null
- 3、
GenericArrayType:通用數(shù)組類型,形如 List<String>[]、T[] 這種數(shù)組類型都是通用數(shù)組類型,接口中值定義了#getGenericComponentType()方法來獲取數(shù)組元素類型。
??代碼演示:
public class GenericArrayTypeTest {
List<String> listArray[] = new ArrayList[10];
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
GenericArrayTypeTest obj = new GenericArrayTypeTest();
Type type = obj.getClass().getDeclaredField("listArray").getGenericType();
if (type instanceof GenericArrayType) {
GenericArrayType genericArrayType = (GenericArrayType) type;
Type componentType = genericArrayType.getGenericComponentType();
System.out.println(componentType);
} else {
System.out.println("type is not GenericArrayType");
}
}
}
??執(zhí)行結(jié)果:
java.util.List<java.lang.String>
- 4、
TypeVariable:類型變量,用來反映在JVM編譯該泛型前的信息,形如 Set<T> 中的 T 就是類型變量,在編譯時(shí)需要被轉(zhuǎn)換為一個(gè)具體的類型后才能正常使用。TypeVariable 同樣也是一個(gè)接口,接口中定義了三個(gè)方法,分別為:-
Type[] getBounds():獲取類型變量的上邊界,如 List<T extends User> 中 T 的上邊界就是 User,如果沒有明確指定上邊界,則為 Object。 -
D getGenericDeclaration():返回聲明該類型變量的原始類型,比如上面的 T 其原始類型為 List。 -
String getName():返回類型變量定義時(shí)的名字,比如 T。
-
??代碼演示:
public class TypeVariableTest<T> {
T arr;
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
TypeVariableTest obj = new TypeVariableTest<String>();
Type type = obj.getClass().getDeclaredField("arr").getGenericType();
if (type instanceof TypeVariable) {
TypeVariable typeVariable = (TypeVariable) type;
for (Type t : typeVariable.getBounds()) {
System.out.println(t);
}
System.out.println(typeVariable.getGenericDeclaration());
System.out.println(typeVariable.getName());
} else {
System.out.println("type is not TypeVariable");
}
}
}
??執(zhí)行結(jié)果:
class java.lang.Object
class com.mybatis.study.TypeVariableTest
T
- 5、
WildcardType:通配符泛型,通配符泛型跟普通泛型相比,區(qū)別在于不僅可以指定類型變量的上邊界如 ? extends Number,還可以指定下邊界 ? super Integer,除此之外,普通泛型使用時(shí)必須指定具體類型,而通配符泛型不需要,適用于具體類型不確定的情況,通常用于帶泛型方法的傳參。WildcardType 接口有兩個(gè)方法,分別為:-
Type[] getUpperBounds():獲取泛型變量的上界。 -
Type[] getLowerBounds():獲取泛型變量的下界。
-
??代碼演示:
public class WildcardTypeTest {
Map<? super Long, ? extends Number> map = new HashMap<>();
public static void test(Type type) {
if (type instanceof WildcardType) {
WildcardType wildcardType = (WildcardType) type;
Type[] uppperTypes = wildcardType.getUpperBounds();
Type[] lowerTypes = wildcardType.getLowerBounds();
System.out.println("UpperType is:");
for (Type t : uppperTypes) {
System.out.println(t);
}
System.out.println("LowerType is:");
for (Type t : lowerTypes) {
System.out.println(t);
}
} else {
System.out.println("type is not WildcardType");
}
}
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
WildcardTypeTest obj = new WildcardTypeTest();
Type type = obj.getClass().getDeclaredField("map").getGenericType();
System.out.println(type);
if (type instanceof ParameterizedType) {
Type[] actTypes = ((ParameterizedType) type).getActualTypeArguments();
for (Type t : actTypes) {
test(t);
System.out.println();
}
}
}
}
??執(zhí)行結(jié)果:
java.util.Map<? super java.lang.Long, ? extends java.lang.Number>
UpperType is:
class java.lang.Object
LowerType is:
class java.lang.Long
UpperType is:
class java.lang.Number
LowerType is:
三、調(diào)用關(guān)系
??TypeParameterResolver 中的方法都是靜態(tài)方法,三個(gè)對外暴露的方法為:
- (1)
#Type resolveFieldType(Field field, Type srcType):解析屬性類型。 - (2)
#Type resolveReturnType(Method method, Type srcType):解析方法返回值類型。 - (3)
#Type[] resolveParamTypes(Method method, Type srcType):解析方法參數(shù)類型,由于一個(gè)方法可能有多個(gè)參數(shù),所以返回的是一個(gè)數(shù)組。
?? 這幾個(gè)方法都會調(diào)用 Type resolveType(Type type, Type srcType, Class<?> declaringClass),該方法根據(jù)傳入的 type 參數(shù)的具體類型,再去調(diào)用其他方法,調(diào)用關(guān)系如圖:

四、方法功能
1、Type resolveFieldType(Field field, Type srcType)
2、Type resolveReturnType(Method method, Type srcType)
3、Type[] resolveParamTypes(Method method, Type srcType)
【功能】解析屬性、返回值、方法參數(shù)類型。
【源碼與注釋】
/**
* 解析屬性類型
*/
public static Type resolveFieldType(Field field, Type srcType) {
// 屬性類型
Type fieldType = field.getGenericType(); // Map<K, V>
// 定義的類
Class<?> declaringClass = field.getDeclaringClass(); // A
// 調(diào)用resolveType進(jìn)行后續(xù)處理,返回具體的類型
return resolveType(fieldType, srcType, declaringClass);
}
/**
* 解析方法返回值類型
*/
public static Type resolveReturnType(Method method, Type srcType) {
// 方法返回值類型
Type returnType = method.getGenericReturnType();
// 定義的類
Class<?> declaringClass = method.getDeclaringClass();
// 調(diào)用resolveType進(jìn)行后續(xù)處理,返回具體的類型
return resolveType(returnType, srcType, declaringClass);
}
/**
* 解析方法參數(shù)類型
*/
public static Type[] resolveParamTypes(Method method, Type srcType) {
// 獲取方法參數(shù)類型數(shù)組
Type[] paramTypes = method.getGenericParameterTypes();
// 定義的類
Class<?> declaringClass = method.getDeclaringClass();
// 解析所有參數(shù)的具體類型,并將結(jié)果保存在數(shù)組中
Type[] result = new Type[paramTypes.length];
for (int i = 0; i < paramTypes.length; i++) {
result[i] = resolveType(paramTypes[i], srcType, declaringClass);
}
return result;
}
【解析】在上述的方法中,傳入的 method、field 參數(shù)可能帶泛型,而擁有(聲明或繼承或?qū)崿F(xiàn))屬性和方法被使用的類 srcType 參數(shù)可能帶具體類型,所以要解析具體類型,要找到哪個(gè)泛型對應(yīng)哪個(gè)具體類型。
4、Type resolveType(Type type, Type srcType, Class<?> declaringClass)
【功能】被公有方法調(diào)用的方法,針對不同類型調(diào)用不同的方法去解析具體的類型信息,起到承上啟下的作用。
【源碼與注解】
private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
// (1) 如果是類型變量,如:T
if (type instanceof TypeVariable) {
return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
// (2) 如果是參數(shù)類型,如:Map<K, V>
// 如果是通配符泛型,如:Map<K extends Xxx, V super Yyy>,
// 因?yàn)槠淇隙ㄊ乔短自趨?shù)類型中的,所以不用去判斷泛型類型是否通配符泛型
} else if (type instanceof ParameterizedType) {
return resolveParameterizedType((ParameterizedType) type, srcType, declaringClass);
// (3) 如果是泛型數(shù)組類型:如:T[]、Map<K, V>[]
} else if (type instanceof GenericArrayType) {
return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
} else {
// (4) 除掉上面四種可能,剩下的只能是Class類型,直接返回
return type;
}
}
5、Type resolveTypeVar(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass)
【功能】解析類型變量的具體類型。
【源碼和注解】
private static Type resolveTypeVar(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass) {
Type result = null; // 保存解析類型變量類型結(jié)果的局部變量
Class<?> clazz = null; // 保存使用類型的原始類型的局部變量
// (1) 使用的類中繼承了帶泛型的父類并在類定義中直接指定泛型類型的情況
if (srcType instanceof Class) {
clazz = (Class<?>) srcType;
// (2) 使用的類中繼承了帶泛型的父類并在類定義中繼續(xù)對外暴露泛型的情況
} else if (srcType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) srcType;
clazz = (Class<?>) parameterizedType.getRawType();
} else {
throw new IllegalArgumentException("The 2nd arg must be Class or ParameterizedType, but was: " + srcType.getClass());
}
// (3) 類中帶泛型,既沒指定具體類型又沒對外暴露,默認(rèn)泛型類型為 Object
if (clazz == declaringClass) {
return Object.class;
}
// (4) 獲取使用類定義時(shí)形式的帶泛型的父類
Type superclass = clazz.getGenericSuperclass();
// (5) 解析類型變量的具體類型
result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superclass);
if (result != null) {
return result;
}
// (6) 類還可能實(shí)現(xiàn)了帶泛型的接口,如果類型變量無法通過父類解析,可能要依賴泛型接口解析
Type[] superInterfaces = clazz.getGenericInterfaces();
for (Type superInterface : superInterfaces) {
result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superInterface);
if (result != null) {
return result;
}
}
//(7)解析不到具體類型,認(rèn)定類型變量可以用作任意類型,即Object
return Object.class;
}
【解析】
??首先明確一下 declaringClass 是帶類型變量的屬性或方法直接聲明的類,srcType 是擁有這些屬性方法被直接使用的類,二者是有區(qū)別的,eg:
static class B<T> {
T t;
}
static class SubClassB extends B<String> {}
??類 SubClassB 通過繼承類 B,擁有了屬性 t,但對屬性 t 來說,聲明它的類是 B,在這個(gè)例子中,srcType 是 SubClassB,declaringClass 是 B。
(1)若使用的類繼承了帶泛型的父類并在類定義中直接指定泛型類型的情況,則 srcType 的具體類型就是 Class,如上面的例子。
(2)若使用的類中繼承了帶泛型的父類并在類定義中繼續(xù)對外暴露泛型的情況,如:
static class SubClassB2<T> extends B<T> {}
則 srcType 為 SubClassB<T>,類型為 ParameterizedType,所以獲取原始類型要通過 ParameterizedType.getRawType() 獲取。
??如果 srcType 不是上面這兩種情況,則是不合理的,直接拋出異常。
(3)類中帶泛型,既沒指定具體類型又沒對外暴露,默認(rèn)泛型類型為 Object,如:
static class SubClassB3 extends B<T> {}
(4)獲取使用類定義時(shí)形式的帶泛型的父類,通過 getGenericSuperclass() 得到的通常是個(gè) ParameterizedType ,如:
static class SubClassB4 extends B<C> {}
SubClassB3 和 SubClassB4 獲得的 super 是不一樣的,分別是 B<T>、B<C>。
(5)解析類型變量的具體類型,調(diào)用 #scanSuperTypes(),其源碼下面結(jié)合例子說明。
(6)類還可能實(shí)現(xiàn)了帶泛型的接口,如果類型變量無法通過父類解析,可能要依賴泛型接口解析,如:
static interface CI<T> {
T getProp();
void setProp(T prop);
}
static class SubClassC implements CI<String> {
String prop;
@Override
public String getProp() {
return prop;
}
@Override
public void setProp(String prop) {
this.prop = prop;
}
}
(7)解析不到具體類型,認(rèn)定類型變量可以用作任意類型,即Object,將上面的例子改改,如下:
static class SubClassC2<T> implements CI<T> {
T prop;
@Override
public T getProp() {
return prop;
}
@Override
public void setProp(T prop) {
this.prop = prop;
}
}
【實(shí)例演示】
(1)類定義
static class B<T> {
T t;
}
static class SubClassB extends B<String> {}
(2)測試代碼
@Test
public void testSubClassB() throws NoSuchFieldException {
Field f = B.class.getDeclaredField("t");
Type type = TypeParameterResolver.resolveFieldType(f, SubClassB.class);
}
【思路分析 -- 主要描述 #scanSuperTypes() 的處理步驟】
- (2.1)泛型的來源:屬性為 B.t,類型為 T,類型為 TypeVariable,B 中的類型變量的數(shù)組為 { T }。
- (2.2)具體類型的來源:SubClass 類定義中直接指定了繼承的父類泛型,所以其泛型父類為 B<String>,泛型類型數(shù)組為 {String}。
- (2.3)關(guān)聯(lián):沿著 SubClass 的繼承鏈追溯,父類為 B,判斷到跟聲明屬性 t 的類一致,所以 {String} 的元素跟 {T} 一一對應(yīng),所以 T 的具體類型是 String。
(3)對測試代碼的第二個(gè)打個(gè)斷點(diǎn),執(zhí)行跟蹤

??在入口方法中,可以看到幾個(gè)傳遞給后面方法的參數(shù)的值,進(jìn)入中轉(zhuǎn)方法

??很明顯,屬性 t 的類型是類型變量,所以交給
#resolveTypeVar 處理
??SubClassB 的類型是 Class,直接類型轉(zhuǎn)換

??對于 SubClassB 來說,擁有的屬性 t 定義的類是 B,條件不成立,所以繼續(xù)解析

??解析到 SubClassB 的帶泛型父類為 B<java.lang.String>,調(diào)用
#scanSuperType() 接著進(jìn)行下一步處理,處理流程如下:
6、ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type srcType, Class<?> declaringClass)
【功能】解析參數(shù)化類型的具體類型。
【源碼與注解】
private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type srcType, Class<?> declaringClass) {
// (1) 獲取參數(shù)化類型的原始類型
Class<?> rawType = (Class<?>) parameterizedType.getRawType();
// (2) 獲取參數(shù)化類型的參數(shù)類型組成的數(shù)組
Type[] typeArgs = parameterizedType.getActualTypeArguments();
Type[] args = new Type[typeArgs.length];
// (3) 遍歷每個(gè)類型,解析其具體類型
for (int i = 0; i < typeArgs.length; i++) {
// (3.1) 參數(shù)類型可能是類型變量
if (typeArgs[i] instanceof TypeVariable) {
args[i] = resolveTypeVar((TypeVariable<?>) typeArgs[i], srcType, declaringClass);
// (3.2) 參數(shù)類型可能是嵌套的參數(shù)化類型
} else if (typeArgs[i] instanceof ParameterizedType) {
args[i] = resolveParameterizedType((ParameterizedType) typeArgs[i], srcType, declaringClass);
// (3.3) 參數(shù)化類型可能是通配符泛型
} else if (typeArgs[i] instanceof WildcardType) {
args[i] = resolveWildcardType((WildcardType) typeArgs[i], srcType, declaringClass);
// (3.4) 可能直接是一個(gè)Class類型
} else {
args[i] = typeArgs[i];
}
}
// (4) 封裝成內(nèi)部類ParameterizedTypeImpl對象返回
return new ParameterizedTypeImpl(rawType, null, args);
}
【解析】
(1)獲取參數(shù)化類型的原始類型,如 List<String> 的原始類型為 List。
(2)獲取參數(shù)化類型的所有參數(shù)類型組成的類型數(shù)組,如 Map<K, V> 的參數(shù)類型數(shù)組為 { K, V }。
(3)遍歷參數(shù)類型數(shù)組中的元素,解析其具體類型。
- (3.1)參數(shù)類型可能是類型變量,如 K。
- (3.2)參數(shù)類型可能是嵌套的參數(shù)化類型,如 List<Map<K, V>>,參數(shù)類型為 Map<K, V>。
- (3.3)參數(shù)化類型可能是通配符泛型,如 Set<? extends Xxx>,參數(shù)類型為 ? extends Xxx。
- (3.4)最常見的參數(shù)化類型是一個(gè)具體類型,即Class,如 List<String>,參數(shù)類型為 String。
(4)封裝成內(nèi)部類ParameterizedTypeImpl對象返回,實(shí)現(xiàn)代碼很簡單,后面再介紹。
【實(shí)例演示】
(1)測試類定義
static class A<K, V> {
Map<K, V> map;
}
static class SubClassA<T> extends A<T, T> {}
static class TestType {
SubClassA<Long> sa = new SubClassA<Long>();
}
(2)測試代碼
@Test
public void testSubClassA2() throws NoSuchFieldException {
Type saType = TestType.class.getDeclaredField("sa").getGenericType();
printTypeInfo(saType);
Field f = A.class.getDeclaredField("map");
Type type = TypeParameterResolver.resolveFieldType(f, saType);
printTypeInfo(type);
}
【解析分析】
- (2.1)泛型的來源:屬性 A.map,類型為 Map<K, V>,A中的類型變量數(shù)組為 { K, V }。
- (2.2)具體類型的來源:TestType 類在定義屬性 sa 時(shí),指定了 SubClassA 中的類型為 Long,所以其泛型父類為 A<Long, Long>,泛型類型數(shù)組具體類型為 { Long, Long }。
- (2.3)關(guān)聯(lián):沿著 SubClassA 的繼承鏈追溯,父類為 A,判斷到跟聲明屬性 map 的類 A 一致,所以具體類型數(shù)組 { Long, Long } 跟泛型類型數(shù)組 { K, V } 一一對應(yīng)。
(3)斷點(diǎn)跟蹤

??屬性類型為 Map<K, V>,聲明類為 A

??type 為 Map<K, V>,這是個(gè)參數(shù)化類型,所以走了第二個(gè)分支,調(diào)用
#resolveParameterizedType() 方法處理
?? Map<K, V> 中的每個(gè)參數(shù)類型都是類型變量,調(diào)用
#resolveTypeVar 處理
??SubClassA<Long> 是一個(gè)參數(shù)化類型,其原始類型為 SubClassA,原始類型定義的泛型父類為 A<T, T>,解析具體類型的步驟如下所示,最終解析出 K 的類型為 Long,V的類型也為Long

7、Type resolveWildcardType(WildcardType wildcardType, Type srcType, Class<?> declaringClass)
【功能】解析通配符泛型的上下界限,并解析每個(gè)界限的具體類型。
【源碼與注解】
private static Type resolveWildcardType(WildcardType wildcardType, Type srcType, Class<?> declaringClass) {
// (1) 獲取通配符泛型的下界數(shù)組,如 ? super Long,獲得數(shù)組為 { Long }
Type[] lowerBounds = resolveWildcardTypeBounds(wildcardType.getLowerBounds(), srcType, declaringClass);
// (2) 獲取通配符泛型的上界數(shù)組,如 ? extends Number,獲得數(shù)組為 { Number }
Type[] upperBounds = resolveWildcardTypeBounds(wildcardType.getUpperBounds(), srcType, declaringClass);
return new WildcardTypeImpl(lowerBounds, upperBounds);
}
private static Type[] resolveWildcardTypeBounds(Type[] bounds, Type srcType, Class<?> declaringClass) {
Type[] result = new Type[bounds.length];
// (3) 解析通配符上界或下界中每個(gè)界限類型的實(shí)際類型
for (int i = 0; i < bounds.length; i++) {
// (3.1) 界限類型是一個(gè)類型變量,eg: <? extends T>
if (bounds[i] instanceof TypeVariable) {
result[i] = resolveTypeVar((TypeVariable<?>) bounds[i], srcType, declaringClass);
// (3.2) 界限類型是一個(gè)參數(shù)化類型,eg: <? super ArrayList<T>>
} else if (bounds[i] instanceof ParameterizedType) {
result[i] = resolveParameterizedType((ParameterizedType) bounds[i], srcType, declaringClass);
// (3.3) 界限類型是一個(gè)嵌套的通配符類型,遞歸調(diào)用,想象不出有什么類型符合這種例子,
// 形如 <? extends <? super Interface1> 形式上符合,但不符合語法和語義
// <? extends Interface1, Interface2> 表示通配的類型要實(shí)現(xiàn)多個(gè)接口,形式上也不會走到這個(gè)分支
} else if (bounds[i] instanceof WildcardType) {
result[i] = resolveWildcardType((WildcardType) bounds[i], srcType, declaringClass);
// (3.4) 界限類型是一個(gè)具體類型,如:<? extends List>
} else {
result[i] = bounds[i];
}
}
return result;
}
【解析】
(1)獲取通配符泛型的下界,如 ? super Long,獲得數(shù)組為 { Long }
(2)獲取通配符泛型的上界數(shù)組,如 ? extends Number,獲得數(shù)組為 { Number }
(3)解析通配符上界或下界中每個(gè)界限類型的實(shí)際類型
- (3.1)界限類型是一個(gè)類型變量,eg: <? extends T>
- (3.2)界限類型是一個(gè)參數(shù)化類型,eg: <? super ArrayList<T>>
- (3.3)界限類型是一個(gè)嵌套的通配符類型,遞歸調(diào)用(想象不出有什么類型符合這種例子)
- (3.4)界限類型是一個(gè)具體類型,如:<? extends List>
8、Type scanSuperTypes(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass, Class<?> clazz, Type superclass)
【功能】沿著繼承鏈,掃描超類,并從超類的具體類型中解析出 typeVar 的具體類型。
【源碼與注解】
private static Type scanSuperTypes(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass, Class<?> clazz, Type superclass) {
Type result = null;
if (superclass instanceof ParameterizedType) {
ParameterizedType parentAsType = (ParameterizedType) superclass;
Class<?> parentAsClass = (Class<?>) parentAsType.getRawType();
if (declaringClass == parentAsClass) {
Type[] typeArgs = parentAsType.getActualTypeArguments();
TypeVariable<?>[] declaredTypeVars = declaringClass.getTypeParameters();
for (int i = 0; i < declaredTypeVars.length; i++) {
if (declaredTypeVars[i] == typeVar) {
if (typeArgs[i] instanceof TypeVariable) {
TypeVariable<?>[] typeParams = clazz.getTypeParameters();
for (int j = 0; j < typeParams.length; j++) {
if (typeParams[j] == typeArgs[i]) {
if (srcType instanceof ParameterizedType) {
result = ((ParameterizedType) srcType).getActualTypeArguments()[j];
}
break;
}
}
} else {
result = typeArgs[i];
}
}
}
// (1)沿著源類型srcType繼承鏈上溯父類,找到聲明了類型變量的父類
} else if (declaringClass.isAssignableFrom(parentAsClass)) {
result = resolveTypeVar(typeVar, parentAsType, declaringClass);
}
// (2)superClass不帶泛型,那么泛型上溯的基類中
} else if (superclass instanceof Class) {
if (declaringClass.isAssignableFrom((Class<?>) superclass)) {
result = resolveTypeVar(typeVar, superclass, declaringClass);
}
}
return result;
}
【解析】
??沒有注釋的分支,在上面的兩個(gè)演示的測試樣例中都演示過了,不再贅述,有可能一次沿著繼承鏈上的基類找不到 typeVar 對應(yīng)的具體類型,那么要繼續(xù)上溯,知道找到對應(yīng)的基類,才能解析到具體的類型,如:
class A<T, S> {
T t;
S s;
}
class B<S> extends A<String, S> {}
class C extends B<Integer> {}
??類 C 擁有繼承來的屬性 t,上溯基類解析具體類型時(shí),泛型表示的父類為 B<Integer>,無法解析 T 的具體類型,因此要繼續(xù)上溯 B<Integer> 的父類 A<String, Integer>,才能解析到為 String,這里的情況其實(shí)就對應(yīng)上面源碼注解(1)處的分支。
class A<T> {
T t;
}
class B extends A<String> {}
class C extends B {}
??換一下代碼,類 C 擁有繼承來的屬性 t,上溯基類解析具體類型時(shí),父類為 B,不帶泛型,無法解析 T 的具體類型,因此要繼續(xù)上溯 B 的父類 A<String>,這里的情況其實(shí)就對應(yīng)上面源碼注解(2)處的分支。
9、Type resolveGenericArrayType(GenericArrayType genericArrayType, Type srcType, Class<?> declaringClass)
【功能】解析泛型數(shù)組類型屬性的元素類型的具體類型。
【代碼與注解】
private static Type resolveGenericArrayType(GenericArrayType genericArrayType, Type srcType, Class<?> declaringClass) {
// (1) 獲取泛型數(shù)組的元素類型
Type componentType = genericArrayType.getGenericComponentType();
Type resolvedComponentType = null;
// (2) 元素類型可能是類型變量,如:T[]
if (componentType instanceof TypeVariable) {
resolvedComponentType = resolveTypeVar((TypeVariable<?>) componentType, srcType, declaringClass);
// (3) 元素類型可能是嵌套的泛型數(shù)組,如:T[S[]]
} else if (componentType instanceof GenericArrayType) {
resolvedComponentType = resolveGenericArrayType((GenericArrayType) componentType, srcType, declaringClass);
// (4) 元素類型可能是參數(shù)化類型,如:T[List<String>]
} else if (componentType instanceof ParameterizedType) {
resolvedComponentType = resolveParameterizedType((ParameterizedType) componentType, srcType, declaringClass);
}
// (5) 元素類型可能是普通具體類型,如:Integer[]
if (resolvedComponentType instanceof Class) {
return Array.newInstance((Class<?>) resolvedComponentType, 0).getClass();
} else {
return new GenericArrayTypeImpl(resolvedComponentType);
}
}
五、內(nèi)部包裝類
1、ParameterizedTypeImpl
【功能】包裝包含參數(shù)化類型具體類型信息的類。
【源碼】
static class ParameterizedTypeImpl implements ParameterizedType {
private Class<?> rawType;
private Type ownerType;
private Type[] actualTypeArguments;
public ParameterizedTypeImpl(Class<?> rawType, Type ownerType, Type[] actualTypeArguments) {
super();
this.rawType = rawType;
this.ownerType = ownerType;
this.actualTypeArguments = actualTypeArguments;
}
@Override
public Type[] getActualTypeArguments() {
return actualTypeArguments;
}
@Override
public Type getOwnerType() {
return ownerType;
}
@Override
public Type getRawType() {
return rawType;
}
@Override
public String toString() {
return "ParameterizedTypeImpl [rawType=" + rawType + ", ownerType=" + ownerType + ", actualTypeArguments=" + Arrays.toString(actualTypeArguments) + "]";
}
}
【解析】
??就是一個(gè)實(shí)現(xiàn)了 ParameterizedType 接口的類,有原始類型、參數(shù)類型、類型所屬類型三個(gè)屬性。
2、WildcardTypeImpl
【功能】包裝通配符泛型具體類型的類。
【源碼】
static class WildcardTypeImpl implements WildcardType {
private Type[] lowerBounds;
private Type[] upperBounds;
private WildcardTypeImpl(Type[] lowerBounds, Type[] upperBounds) {
super();
this.lowerBounds = lowerBounds;
this.upperBounds = upperBounds;
}
@Override
public Type[] getLowerBounds() {
return lowerBounds;
}
@Override
public Type[] getUpperBounds() {
return upperBounds;
}
}
【解析】
??實(shí)現(xiàn)了 WildcardType 接口,保存通配的界限類型的具體類型信息。
3、GenericArrayTypeImpl
【功能】保存泛型數(shù)組元素類型的具體類型信息的類。
【源碼】
static class GenericArrayTypeImpl implements GenericArrayType {
private Type genericComponentType;
private GenericArrayTypeImpl(Type genericComponentType) {
super();
this.genericComponentType = genericComponentType;
}
@Override
public Type getGenericComponentType() {
return genericComponentType;
}
}
【解析】
??實(shí)現(xiàn)了 GenericArrayType 接口,保存元素具體類型信息。
PS.入口傳入要解析的類型如果可以解析出具體類型,則返回對應(yīng)的Class對象,否則都用上面三個(gè)內(nèi)部類包裝返回,由于類型有可能是嵌套的,所以返回這些包裝類時(shí),包裝類之間也有可能是嵌套的,所以外部調(diào)用程序使用返回的類型時(shí),如果判斷到不是Class對象,獲取包裝的具體類型信息時(shí)也要嵌套地去獲取具體的類型信息。