Java反射获取
获取类上的泛型
获取父类定义的泛型
例如现在有一个父类
public abstract class TestClass<E> {
......
}
同时他有多个实现类,如
public class TestStringClass extends TestClass<String>{
....
}
public class TestIntegerClass extends TestClass<Integer>{
....
}
....
此时如果要获取该类上声明的泛型
需要用到Class类中的getGenericSuperclass
方法
getGenericSuperclass方法的作用是:
返回该class所表示的实体(类、接口、原始类型或void)的直接父类的Type。如果父类是参数化类型(即有泛型定义),那么返回的Type对象必须准确的反应源代码中使用的实际类型参数。
如果是带有泛型的父类,则会返回
ParameterizedType
,如果当前Class是Object类,接口,原始类型或者void,则会返回null。如果此对象表示数组类,则返回表示Object类的Class对象。
ParameterizedType类有3个方法,其中getActualTypeArguments
能获取到泛型列表的数组。
那么在父类中,如果要获取子类声明的泛型类型,就可以使用此方法
Type genericSuperclass = this.getClass().getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println(actualTypeArgument);
}
}
如此一来,就可以获取到父类的泛型了。
public abstract class TestClass<E> {
public void print(){
Type genericSuperclass = this.getClass().getGenericSuperclass();
List<Type> list = null;
if (genericSuperclass instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
list = Arrays.asList(actualTypeArguments);
}
System.out.println(this.getClass() + " 的泛型 = " + list);
}
}
public class TestStringClass extends TestClass<String>{
public static void main(String[] args) {
TestStringClass testStringClass = new TestStringClass();
testStringClass.print();
}
}
// class xxx.TestStringClass 的泛型 = [class java.lang.String]
public class TestMapClass extends TestClass<Map<String,String>>{
public static void main(String[] args) {
TestMapClass testMapClass = new TestMapClass();
testMapClass.print();
}
}
// class xxx.TestMapClass 的泛型 = [java.util.Map<java.lang.String, java.lang.String>]
如果我们想获取泛型中的泛型,例如上面的TestClass<Map<String,String>>中的Map的泛型。
我们可以看到ParameterizedType有很多实现类,其中java原生的实现类为sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
这个实现类中也有一个actualTypeArguments属性,也就是说,可以继续尝试获取泛型列表
获取接口定义的泛型
很多的接口上也定义了泛型描述,可以通过Class的getGenericInterfaces
方法获取,因为一个类可以实现多个接口,所以返回了一个Type数组,可以遍历数组,找到需要处理的接口对应的Type,其余的操作就获取父类上的泛型操作一致了。
获取属性的泛型
获取属性的泛型,先通过Class,获取到需要获取泛型的Field,然后过个Field类的getGenericType
方法获取到Type,其余操作与获取父类上的泛型操作一致。
通过Spring工具类获取
spring-core工程中,提供了一个ResolvableType
工具类,他可以从属性、方法参数、方法返回、类中后去对应的泛型。从Spring4.0开始提供这个工具类。
常用的方法有
forField(Field field) 获取属性的泛型
forMethodParameter(Method method, int parameterIndex) 获取方法指定参数的泛型
forMethodReturnType(Method method) 获取方法返回值的泛型
forConstructorParameter(Constructor constructor, int parameterIndex) 获取构造函数指定参数的泛型
forClass(Class clazz) 获取class的泛型
forType(Type type) 获取type的泛型
forInstance(Object) 通过实体获取泛型
官方示例:
private HashMap<Integer, List<String>> myMap;
public void example() {
ResolvableType t = ResolvableType.forField(getClass().getDeclaredField("myMap"));
t.getSuperType(); // AbstractMap<Integer, List<String>>
t.asMap(); // Map<Integer, List<String>>
// 获取指定下标的泛型类型
t.getGeneric(0).resolve(); // Integer
t.getGeneric(1).resolve(); // List
t.getGeneric(1); // List<String>
// 获取指定下标的泛型的指定下标的泛型,即获取嵌套泛型的泛型
t.resolveGeneric(1, 0); // String
}