Java如何获取泛型类型

Radinka ·
更新时间:2024-09-21
· 688 次阅读

参考:我眼中的Java-Type体系(1)
我眼中的Java-Type体系(2)
秒懂Java类型(Type)系统
Java 运行时如何获取泛型参数的类型
Java类型Type 之 ParameterizedType,GenericArrayType,TypeVariabl,WildcardType

从实现的接口获取泛型参数

定义一个泛型父类:

public interface SuperClass

{ String process(P p); }

实现类1:

public class OneImpl implements SuperClass { @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

,所以会返回 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 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> arrayLists, 第一次获取到的类型还是 ParameterizedType 类型 if (actualType instanceof ParameterizedType) { return getActualClass(actualType); } } return actualClasses; } return null; } class OneGenericClass { public void go(long userId, ArrayList<ArrayList> arrayLists, List orderIds, Map map, List[] listArr) { System.out.println(userId); System.out.println(orderIds); } } 输出: class: long java.util.ArrayList<java.util.ArrayList>, ParameterizedType, holderType: class java.util.ArrayList, actual parameterized classes: [class java.lang.String] java.util.List, ParameterizedType, holderType: interface java.util.List, actual parameterized classes: [class java.lang.Long] java.util.Map, ParameterizedType, holderType: interface java.util.Map, actual parameterized classes: [class java.lang.String, class java.lang.Integer] java.util.List[], GenericArrayType, actual classes: [class java.lang.Long] 从 Field 获取泛型参数 public class GenericTest1 { private List[] listArray; private List 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,得到的 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[] 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 类型 for (Type type : parameterTypes) { System.out.println(type.getClass().getName()); System.out.println(type); } // 定义这个 List 的类型 System.out.println(fieldList.getType()); } } 输出: java.util.List 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,然后再通过得到的类型做不同的处理。


作者:jiaobuchong



泛型类型 JAVA 泛型类 泛型

需要 登录 后方可回复, 如果你还没有账号请 注册新账号