欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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,然后再通过得到的类型做不同的处理。

相关标签: Java零碎