Java如何获取泛型类型
程序员文章站
2022-06-01 10:39:58
...
参考:我眼中的Java-Type体系(1)
我眼中的Java-Type体系(2)
Java 运行时如何获取泛型参数的类型
Java类型Type 之 ParameterizedType,GenericArrayType,TypeVariabl,WildcardType
从实现的接口获取泛型参数
定义一个泛型父类:
public interface SuperClass<P> {
String process(P p);
}
实现类1:
public class OneImpl implements SuperClass<House> {
@Override
public String process(House house) {
return null;
}
}
测试一下:
public static void main(String[] args) throws Exception {
SuperClass superClass = new OneImpl();
// 获取运行时类型
System.out.println(superClass.getClass());
// 获取实现的接口
Type[] types = superClass.getClass().getGenericInterfaces();
for (Type t : types) {
// ParameterizedType 的实现类:ParameterizedTypeImpl
System.out.println("ParameterizedTypeImpl: " + t.getClass().getName());
// 带有泛型信息
System.out.println(t);
System.out.println(t instanceof ParameterizedType);
// 获取声明这个泛型的类或接口
System.out.println(((ParameterizedType) t).getRawType());
// 获取泛型中的实际类型,可能存在多个泛型,比如 SuperClass<P, R>,所以会返回 Type[] 数组
Type[] paramGenericTypes = ((ParameterizedType) t).getActualTypeArguments();
for (Type actualType : paramGenericTypes) {
// 得到泛型的实际类型,这里也就得到了 Class 类型
System.out.println("actualTypeName: " + actualType.getClass().getName());
System.out.println(actualType);
}
}
System.out.println("------------------------------");
// 获取实现的接口
Class[] t = superClass.getClass().getInterfaces();
for (Class c : t) {
System.out.println(c);
}
}
输出:
class com.jiaobucong.common.core.generic.OneImpl
ParameterizedTypeImpl: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
com.jiaobucong.common.core.generic.SuperClass<com.jiaobucong.common.core.generic.House>
true
interface com.jiaobucong.common.core.generic.SuperClass
actualTypeName: java.lang.Class
class com.jiaobucong.common.core.generic.House
------------------------------
interface com.jiaobucong.common.core.generic.SuperClass
实现类2,不带泛型:
public class TwoImpl implements SuperClass {
@Override
public String process(Object o) {
return null;
}
}
来看测试:
public static void main(String[] args) throws Exception {
SuperClass superClass1 = new TwoImpl();
Type[] types1 = superClass1.getClass().getGenericInterfaces();
for (Type type : types1) {
System.out.println(type);
// 实现类没有指定泛型参数,没有对应的 ParameterizedTypeImpl 实现类
System.out.println(type instanceof ParameterizedType);
}
}
输出:
interface com.jiaobucong.common.core.generic.SuperClass
false
通过 Method 方法级获取泛型参数
public class GenericArrayTest {
public static void main(String[] args) throws Exception {
Method[] methods = OneGenericClass.class.getMethods();
for (Method method : methods) {
// 获取每个方法的参数化类型
if (!"go".equals(method.getName())) {
continue;
}
Type[] parameters = method.getGenericParameterTypes();
for (Type type : parameters) {
// 不同的参数定义返回的类型也是不一样的
if (type instanceof Class) {
// 第一个参数
System.out.println("class: " + type);
} else if (type instanceof ParameterizedType) {
// 声明这个泛型的类
Class<?> clazz = (Class<?>) ((ParameterizedType) type).getRawType();
System.out.println(type + ", ParameterizedType, "
+ "holderType: " + clazz
+ ", actual parameterized classes: "
+ Arrays.toString(getActualClass(type)));
} else if(type instanceof GenericArrayType) {
// 对于数组类型得到的是 GenericArrayType
Type arrayType = ((GenericArrayType) type).getGenericComponentType();
System.out.println(type + ", GenericArrayType, actual classes: "
+ Arrays.toString(getActualClass(arrayType)));
}
}
}
}
public static Class<?>[] getActualClass(Type type) {
if (type instanceof ParameterizedType) {
Type[] actualTypes = ((ParameterizedType) type).getActualTypeArguments();
Class<?>[] actualClasses = new Class[actualTypes.length];
for (int i = 0; i < actualTypes.length; i++) {
Type actualType = actualTypes[i];
if (actualType instanceof Class) {
actualClasses[i] = (Class<?>) actualType;
}
// ArrayList<ArrayList<String>> arrayLists, 第一次获取到的类型还是 ParameterizedType 类型
if (actualType instanceof ParameterizedType) {
return getActualClass(actualType);
}
}
return actualClasses;
}
return null;
}
class OneGenericClass {
public void go(long userId, ArrayList<ArrayList<String>> arrayLists, List<Long> orderIds, Map<String, Integer> map, List<Long>[] listArr) {
System.out.println(userId);
System.out.println(orderIds);
}
}
输出:
class: long
java.util.ArrayList<java.util.ArrayList<java.lang.String>>, ParameterizedType, holderType: class java.util.ArrayList, actual parameterized classes: [class java.lang.String]
java.util.List<java.lang.Long>, ParameterizedType, holderType: interface java.util.List, actual parameterized classes: [class java.lang.Long]
java.util.Map<java.lang.String, java.lang.Integer>, ParameterizedType, holderType: interface java.util.Map, actual parameterized classes: [class java.lang.String, class java.lang.Integer]
java.util.List<java.lang.Long>[], GenericArrayType, actual classes: [class java.lang.Long]
从 Field 获取泛型参数
public class GenericTest1 {
private List<String>[] listArray;
private List<Long> list;
public static void main(String[] args) throws Exception {
test1();
System.out.println("-------------------test2");
test2();
}
public static void test1() throws Exception {
Field fieldListArray = GenericTest1.class.getDeclaredField("listArray");
Type type = fieldListArray.getGenericType();
// 这里会报错,得到的不是一个 ParameterizedType
// Type[] arrayType = ((ParameterizedType) type).getActualTypeArguments();
// 得到的是一个GenericArrayType,这个地方是一个泛型数组的类型,所以得到的是 GenericArrayType
// 得到的类型是去掉了最右边的[],是 List<String>,得到的 arrayType 是 ParameterizedType
Type arrayType = ((GenericArrayType) type).getGenericComponentType();
System.out.println(arrayType);
System.out.println(arrayType.getClass().getName());
Type[] types = ((ParameterizedType) arrayType).getActualTypeArguments();
for (Type type1 : types) {
System.out.println(type1.getClass().getName());
// 这里获取到了 List<String>[] listArray <> 中的 String 类型
System.out.println(type1);
}
}
public static void test2() throws Exception {
Field fieldList = GenericTest1.class.getDeclaredField("list");
Type typeList = fieldList.getGenericType();
System.out.println(typeList.getClass().getName());
Type[] parameterTypes = ((ParameterizedType) typeList).getActualTypeArguments();
// 获取 List<T> 中的 T 类型
for (Type type : parameterTypes) {
System.out.println(type.getClass().getName());
System.out.println(type);
}
// 定义这个 List 的类型
System.out.println(fieldList.getType());
}
}
输出:
java.util.List<java.lang.String>
sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
java.lang.Class
class java.lang.String
-------------------test2
sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
java.lang.Class
class java.lang.Long
interface java.util.List
我们可以在类接口上、构造器上、方法上定义泛型类型,不同的泛型参数定义得到可能是 ParameterizedType、TypeVariable、Class、GenericArrayType,然后再通过得到的类型做不同的处理。
下一篇: 华为西欧高管戢仁贵:华为终将成为世界第一