Type类
Type是Java所有类型的父接口,它包含Class类型(普通Class类),参数化类型(泛型,带<>的类),数组类型(数组,如String[],Object[]等),还有参数化类型(泛型类<>里面的类型,如K,V,泛指任何类)和基本类型(int,long,float等基本类型)。
Type类的子接口
根据上面Type类的描述,Type被分为几类,就对应了几个不同的子接口:
Class
包含了普通类和基本类型。
ParameteredType
泛型类,含有<>泛型信息的类。
public interface ParameterizedType extends Type {
// 获取泛型类内部的类型,即<>里面的类型,如Map<K,V>就得到了K和V的类型数组;
Type[] getActualTypeArguments();
// 获取原始类型,即去掉<>的类型,如Map<K,V>就得到了Map类型;
Type getRawType();
// 获取宿主类型,如果此泛型类定义在子类,该方法获取到的是父类的类型;
Type getOwnerType();
}
TypeVariable
参数类型,泛指任何类,如Map中的K和V;
public interface TypeVariable<D extends GenericDeclaration> extends Type/*, AnnotatedElement*/ {
// 获取类型的上边界
Type[] getBounds();
// GenericDeclaration的子类是Method,Class,Constructor等,该方法就是获取此类型所声明的地方
D getGenericDeclaration();
// 获取类型的名称
String getName();
}
WildcardType
代表通配符表达式,或泛型表达式,比如<? extends T> <? super T>
public interface WildcardType extends Type {
// 获取限制类型的上边界
Type[] getUpperBounds();
//获取限制类型的下边界
Type[] getLowerBounds();
}
GenericArrayType
代表泛型类型数组,如T[],其中T是TypeVariable类型。
public interface GenericArrayType extends Type {
// 数组中的元素类型
Type getGenericComponentType();
}
通过反射获取类型信息
我通过写一个测试例子来说明以上所有Type的子类型,主要有几个步骤:
- 声明一个类,在类中声明一个方法,方法的参数包含以上描述的Type的5中类型;
- 通过反射获取该方法的所有包含泛型的参数类型列表:Method.getGenericParameterTypes(Method也有一个接口getParameterTypes获取的是不包含泛型的参数类型列表,即会去除<>信息);
- 遍历getGenericParameterTypes获取到的Type数组,针对每个Type元素就可识别出是哪一种子类型;
- 从getGenericParameterTypes获取到的Type元素,可调用getActualTypeArguments接口获取泛型类<>里面的类型列表,如果<>又有泛型,可层层递归获取到最终的非泛型类型;
代码例子:
public class ParameterizeTest {
@Test
public void test() {
Method[] methods = ParameterizeTest.class.getMethods();
Method tMethod = null;
for (Method method : methods) {
if ("invokeParameter".equals(method.getName())) {
tMethod = method;
}
}
// getParameterTypes获取到的是不包含泛型信息的类型,这里是为了和getGenericParameterTypes对比
Type[] commonTypes = tMethod.getParameterTypes();
for (Type type : commonTypes) {
System.out.println("CommonType = " + type + ", ParamTypeCategory = " + type.getClass().getSimpleName());
}
System.out.println();
// getGenericParameterTypes获取到的是包含泛型信息的类型
Type[] genericTypes = tMethod.getGenericParameterTypes();
for (Type type : genericTypes) {
System.out.println("ParamType = " + type + ", ParamTypeCategory = " + type.getClass().getSimpleName());
if (type instanceof ParameterizedType) {
Type[] actualTypes = ((ParameterizedType) type).getActualTypeArguments();
for (int i = 0; i < actualTypes.length; i++) {
Type aType = actualTypes[i];
System.out.println("\t" + i + " actualType = " + aType + ", actualTypeCategory = " + aType.getClass().getInterfaces()[0].getName());
if (aType instanceof WildcardType) {
Type[] lower = ((WildcardType) aType).getLowerBounds();
Type[] upper = ((WildcardType) aType).getUpperBounds();
System.out.println("\t\tLowerBounds = " + Arrays.toString(lower) + ", UpperBounds = " + Arrays.toString(upper));
} else if (aType instanceof TypeVariable) {
Type[] bounds = ((TypeVariable<?>) aType).getBounds();
String name = ((TypeVariable<?>) aType).getName();
GenericDeclaration declaration = ((TypeVariable<?>) aType).getGenericDeclaration();
System.out.println("\t\tName = " + name + ", Declaration = " + declaration + ", Bounds = " + Arrays.toString(bounds));
} else if (aType instanceof ParameterizedType) {
System.out.println("\t\tRawType = " + ((ParameterizedType) aType).getRawType() + ", OwnerType = " + ((ParameterizedType) aType).getOwnerType()
+ ", ActualTypeArguments = " + Arrays.toString(((ParameterizedType) aType).getActualTypeArguments()));
}
}
} else if (type instanceof GenericArrayType) {
System.out.println("\t\tGenericComponentType = " + ((GenericArrayType) type).getGenericComponentType());
}
}
}
public <T, K extends String, V> void invokeParameter(String a0, Map<K, V> a1, List<List<T>> a2, List<? super String> a3, T[] a4, String[] a5) {
}
}
运行结果:
CommonType = class java.lang.String, ParamTypeCategory = Class
CommonType = interface java.util.Map, ParamTypeCategory = Class
CommonType = interface java.util.List, ParamTypeCategory = Class
CommonType = interface java.util.List, ParamTypeCategory = Class
CommonType = class [Ljava.lang.Object;, ParamTypeCategory = Class
CommonType = class [Ljava.lang.String;, ParamTypeCategory = Class
ParamType = class java.lang.String, ParamTypeCategory = Class
//ParameterizedTypeImpl是ParameterizedType的实现类
ParamType = java.util.Map<K, V>, ParamTypeCategory = ParameterizedTypeImpl是
0 actualType = K, actualTypeCategory = java.lang.reflect.TypeVariable
Name = K, Declaration = public void com.example.myapplication.ParameterizeTest.invokeParameter(java.lang.String,java.util.Map,java.util.List,java.util.List,java.lang.Object[],java.lang.String[]), Bounds = [class java.lang.String]
1 actualType = V, actualTypeCategory = java.lang.reflect.TypeVariable
Name = V, Declaration = public void com.example.myapplication.ParameterizeTest.invokeParameter(java.lang.String,java.util.Map,java.util.List,java.util.List,java.lang.Object[],java.lang.String[]), Bounds = [class java.lang.Object]
ParamType = java.util.List<java.util.List<T>>, ParamTypeCategory = ParameterizedTypeImpl
0 actualType = java.util.List<T>, actualTypeCategory = java.lang.reflect.ParameterizedType
RawType = interface java.util.List, OwnerType = null, ActualTypeArguments = [T]
ParamType = java.util.List<? super java.lang.String>, ParamTypeCategory = ParameterizedTypeImpl
0 actualType = ? super java.lang.String, actualTypeCategory = java.lang.reflect.WildcardType
LowerBounds = [class java.lang.String], UpperBounds = [class java.lang.Object]
ParamType = T[], ParamTypeCategory = GenericArrayTypeImpl
GenericComponentType = T
ParamType = class [Ljava.lang.String;, ParamTypeCategory = Class