通过反射可以获取类的字段和方法,但是有些类型是带有泛型参数的,那么进一步如何获取泛型的实际类型呢,常见的有三种方式,每一种方式都对应一种适应场景,不能混用:
- 获取类(接口)上的泛型参数的实际类型
- 获取方法参数上泛型参数的实际类型
- 获取字段上泛型参数的实际类型
代码如下:
定义一个接口和其实现类(测试验证用):
/**
* 定义一个带泛型参数的接口
*/
public interface IMessageSender<T,V> {
V sendMsg(T msg);
}
/**
* 实现两接口:
* 一个带泛型参数(验证获取其泛型参数),一个不带泛型参数(测试对比用)
*/
public class SmsMessageImpl implements
IMessageSender<String, List<Integer>>, Serializable {
@Override
public List<Integer> sendMsg(String msg) {
return new ArrayList<>();
}
}
获取泛型的实际类型的三种方式的代码示例:
public class TypeTest {
/**
* 1.获取类(接口)上的泛型参数的实际类型
*/
@Test
public void testClassGenericActualType(){
//该类实现了两个接口分别是:IMessageSender<String, List<Integer>> 和 Serializable
Type genericInterface1 = SmsMessageImpl.class.getGenericInterfaces()[0];
Type genericInterface2 = SmsMessageImpl.class.getGenericInterfaces()[1];
//第一个是带泛型参数的接口:IMessageSender<String, List<Integer>>,
//因此Type实际上是ParameterizedType类型:sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
System.out.println(genericInterface1.getClass());
//第二个是不带泛型参数的接口,因此Type是普通Class类型:class java.lang.Class
System.out.println(genericInterface2.getClass());
//获取泛化的接口参数的实际类型(先强转为ParameterizedType)
Type[] actualTypeArguments = ((ParameterizedType) genericInterface1).getActualTypeArguments();
//分别获取该类上的两个泛型参数的实际类型:String 和 List<Integer>
System.out.println(actualTypeArguments[0] + " , "+ actualTypeArguments[1]);
//其中List<Integer>可以继续获取其元素泛型的类型:Integer
System.out.println(((ParameterizedType)actualTypeArguments[1]).getActualTypeArguments()[0]);
}
/**
* 2. 获取方法参数上泛型参数的实际类型
*/
@Test
public void testMethodGenericActualType() throws NoSuchMethodException {
Method method = TypeTest.class.getMethod("verify", Map.class);
Parameter parameter = method.getParameters()[0];
Type type = parameter.getParameterizedType();
//由于参数是带泛型的,因此type的实际类型是ParameterizedType,
//可以强制转换为ParameterizedType,然后获取参数Map中的两个泛型参数: <String,Integer>
Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
System.out.println(actualTypeArguments[0] + " , " + actualTypeArguments[1]);
}
/**
* 3.获取字段上泛型参数的实际类型
*/
@Test
public void testFieldGenericActualType() throws NoSuchFieldException {
Field field = TypeTest.class.getDeclaredField("list");
Type genericType = field.getGenericType();
Type[] actualTypeArguments = ((ParameterizedType) genericType).getActualTypeArguments();
//得到字段List<String>泛型中的实际类型String
System.out.println(actualTypeArguments[0]);
}
public void verify(Map<String,Integer> map){
//测试备用方法
}
private List<String> list;
}