Java通过反射获取泛型类型信息
Posted 二木成林
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java通过反射获取泛型类型信息相关的知识,希望对你有一定的参考价值。
概述
通常泛型在如下几种情况下使用:
- 含有泛型的类
// 格式
修饰符 class 类名<代表泛型的变量> { }
// 实例
public class ArrayList<E> {
public boolean add(E e){ }
public E get(int index){ }
}
- 含有泛型的方法
// 格式
修饰符 <代表泛型的变量> 返回值类型 方法参数(参数) { }
// 实例
public class MyGenericClass {
public <ABC> void print(ABC abc) {
System.out.println(abc);
}
}
- 含有泛型的接口
// 格式
修饰符 interface 接口名<代表泛型的变量> { }
// 实例
public interface MyGenericInterface<E> {
public abstract void add(E e);
public abstract E getE();
}
泛型的使用场景就是如上三种,当在类或接口中定义了泛型后,就可以在类或接口中的成员变量、方法参数、方法返回值中也使用泛型;当定义了含有泛型的方法后,就可以在该方法的方法参数、方法返回值和方法内局部变量中使用泛型。
反射获取泛型的场景
在Java中可以通过反射获取泛型信息的场景有如下三个:
- (1)成员变量的泛型
- (2)方法参数的泛型
- (3)方法返回值的泛型
在Java中不可以通过反射获取泛型信息的场景有如下两个:
- (1)类或接口声明的泛型
- (2)局部变量的泛型
实例
我们先创建一个类,该类中正好有含有泛型的成员变量、含有泛型的方法返回值、含有泛型的方法参数。代码如下:
class MyClass {
// 带有泛型的成员变量
public List<Object> list = new ArrayList<>();
// 方法返回值中带有泛型
public List<Object> getList() {
return list;
}
// 方法参数带有泛型
public void setList(List<Object> list) {
this.list = list;
}
}
要获取泛型信息,必须要注意ParameterizedType类,该类中的getActualTypeArguments()方法可以有效获取泛型信息。
具体的实例代码如下:
public class Demo {
public static void main(String[] args) throws NoSuchMethodException, NoSuchFieldException {
// 获取成员方法返回值的泛型类型信息
getMethodReturnValueGeneric();
System.out.println("======================================");
// 获取成员变量的泛型类型信息
getMemberVariablesGeneric();
System.out.println("======================================");
// 获取成员方法参数的泛型类型信息
getMethodParametricGeneric();
}
/**
* 获取方法返回值的泛型类型信息
*
* @throws NoSuchMethodException
*/
public static void getMethodReturnValueGeneric() throws NoSuchMethodException {
// 获取名为"getList"的方法,在MyClass类中
Method getListMethod = MyClass.class.getMethod("getList");
// 获取返回值类型,getGenericReturnType()会返回值带有泛型的返回值类型
Type genericReturnType = getListMethod.getGenericReturnType();
// 但我们实际上需要获取返回值类型中的泛型信息,所以要进一步判断,即判断获取的返回值类型是否是参数化类型ParameterizedType
if (genericReturnType instanceof ParameterizedType) {
// 如果要使用ParameterizedType中的方法,必须先强制向下转型
ParameterizedType type = (ParameterizedType) genericReturnType;
// 获取返回值类型中的泛型类型,因为可能有多个泛型类型,所以返回一个数组
Type[] actualTypeArguments = type.getActualTypeArguments();
// 循环数组,遍历每一个泛型类型
for (Type actualTypeArgument : actualTypeArguments) {
Class typeArgClass = (Class) actualTypeArgument;
System.out.println("成员方法返回值的泛型信息:" + typeArgClass);
}
}
}
/**
* 获取类中成员变量的泛型类型信息
*
* @throws NoSuchFieldException
*/
public static void getMemberVariablesGeneric() throws NoSuchFieldException {
// 获取MyTestClass类中名为"list"的字段
Field listField = MyClass.class.getField("list");
// 获取该字段的类型信息,getGenericType()方法能够获取带有泛型的类型信息
Type genericType = listField.getGenericType();
// 但我们实际上需要获取返回值类型中的泛型信息,所以要进一步判断,即判断获取的返回值类型是否是参数化类型ParameterizedType
if (genericType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericType;
// 获取成员变量的泛型类型信息
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
Class fieldArgClass = (Class) actualTypeArgument;
System.out.println("成员变量的泛型信息:" + fieldArgClass);
}
}
}
/**
* 获取方法参数的泛型类型信息
*
* @throws NoSuchMethodException
*/
public static void getMethodParametricGeneric() throws NoSuchMethodException {
// 获取MyTestClass类中名为"setList"的方法
Method setListMethod = MyClass.class.getMethod("setList", List.class);
// 获取该方法的参数类型信息(带有泛型)
Type[] genericParameterTypes = setListMethod.getGenericParameterTypes();
// 但我们实际上需要获取返回值类型中的泛型信息,所以要进一步判断,即判断获取的返回值类型是否是参数化类型ParameterizedType
for (Type genericParameterType : genericParameterTypes) {
ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;
// 获取成员方法参数的泛型类型信息
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
Class realType = (Class) actualTypeArgument;
System.out.println("成员方法参数的泛型信息:" + realType);
}
}
}
}
/*打印结果:
成员方法返回值的泛型信息:class java.lang.Object
======================================
成员变量的泛型信息:class java.lang.Object
======================================
成员方法参数的泛型信息:class java.lang.Object
*/
以上是关于Java通过反射获取泛型类型信息的主要内容,如果未能解决你的问题,请参考以下文章