ParameterizedType类的使用

Posted 二木成林

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ParameterizedType类的使用相关的知识,希望对你有一定的参考价值。

API

ParameterizedType是一个接口,有三个方法,它的API如下:

/**
 * ParameterizedType 表示参数化类型,例如 Collection<String>。
 * 参数化类型在反射方法第一次需要时创建,如本包中所指定。 创建参数化类型 p 时,解析 p 实例化的泛型类型声明,并递归创建 p 的所有类型参数。 有关类型变量创建过程的详细信息,请参阅TypeVariable 。 重复创建参数化类型无效。
 * 实现此接口的类的实例必须实现一个 equals() 方法,该方法等同于共享相同泛型类型声明并具有相同类型参数的任何两个实例。
 *
 * @since:1.5
 */
public interface ParameterizedType extends Type {

    /**
     * 返回一个Type对象数组,表示该类型的实际类型参数。
     * 请注意,在某些情况下,返回的数组为空。 如果此类型表示嵌套在参数化类型中的非参数化类型,则会发生这种情况。
     *
     * @return: 表示此类型的实际类型参数的Type对象数组
     * @throws TypeNotPresentException 如果任何实际类型参数引用不存在的类型声明
     * @throws MalformedParameterizedTypeException 如果任何实际类型参数引用了由于任何原因无法实例化的参数化类型
     * @since 1.5
     */    
    Type[] getActualTypeArguments();

    /**
     * 返回表示声明此类型的类或接口的Type对象。
     *
     * @return 表示声明此类型的类或接口的Type对象
     * @since 1.5
     */
    Type getRawType();

    /**
     * 返回一个Type对象,表示该类型所属的类型。 例如,如果此类型为O<T>.I<S> ,则返回O<T> 。
     * 如果此类型是顶级类型,则返回null 。
     *
     * @return 一个Type对象,表示该类型所属的类型。 如果此类型是顶级类型,则返回null。
     * @throws 如果所有者类型引用不存在的类型声明
     * @throws 如果所有者类型引用了由于任何原因无法实例化的参数化类型
     * @since 1.5
     */
    Type getOwnerType();
}

概述

ParameterizedType接口顾名思义就是参数化类型。例如List、String这种不是参数化类型,凡是这种带有泛型的类型如Collection<String>、Map<String, Object>就是参数化类型。

我们可以通过下面的类来验证哪些类型是参数化类型。

public class Test {
    public static void main(String[] args) {
        // 创建实体类对象
        MyTestClass myClass = new MyTestClass();
        // 获取Class类对象,然后获取该类中所有声明的字段
        Field[] fields = myClass.getClass().getDeclaredFields();
        // 循环遍历字段数组
        for (Field field : fields) {
            // 注意getType()和getGenericType()方法的区别:getType()方法是获取字段的类型,返回Class对象;getGenericType()方法也是获取字段的类型,但包括泛型,返回Type对象
            System.out.println("getType()=" + field.getType());
            System.out.println("getGenericType()=" + field.getGenericType());
            // 下面就是通过instanceof关键字来判断该类型是否是参数化类型
            System.out.println("genericType instanceof ParameterizedType=" + (field.getGenericType() instanceof ParameterizedType));
            System.out.println("========================");
        }
    }
}

class MyTestClass {
    public int i;
    public String str;
    public List list;
    public List<String> stringList;
    public Map map;
    public Map<String, Object> stringObjectMap;
}
/*打印结果:
    getType()=int
    getGenericType()=int
    genericType instanceof ParameterizedType=false
    ========================
    getType()=class java.lang.String
    getGenericType()=class java.lang.String
    genericType instanceof ParameterizedType=false
    ========================
    getType()=interface java.util.List
    getGenericType()=interface java.util.List
    genericType instanceof ParameterizedType=false
    ========================
    getType()=interface java.util.List
    getGenericType()=java.util.List<java.lang.String>
    genericType instanceof ParameterizedType=true
    ========================
    getType()=interface java.util.Map
    getGenericType()=interface java.util.Map
    genericType instanceof ParameterizedType=false
    ========================
    getType()=interface java.util.Map
    getGenericType()=java.util.Map<java.lang.String, java.lang.Object>
    genericType instanceof ParameterizedType=true
    ========================
 */

发现确实是带有泛型的类型才是参数化类型。

方法说明

Type[] getActualTypeArgument()

该方法返回一个Type数组,该数组中是参数化类型的参数。比如List<String>类型调用该方法后返回的参数化类型就是String;如Map<String, Object>类型调用该方法后返回的参数化类型就有两个String和Object。

public class Test {
    public static void main(String[] args) {
        // 创建实体类对象
        MyTestClass myClass = new MyTestClass();
        // 获取Class类对象,然后获取该类中所有声明的字段
        Field[] fields = myClass.getClass().getDeclaredFields();
        // 循环遍历字段数组
        for (Field field : fields) {
            Type genericType = field.getGenericType();
            // 必须是ParameterizedType类型才能做接下来的操作,所以需要先判断
            if (genericType instanceof ParameterizedType) {
                // 首先要强制转型成ParameterizedType类型,才能调用方法
                ParameterizedType parameterizedType = (ParameterizedType) genericType;
                // 调用getActualTypeArguments()方法获取实际的参数化类型,即具体是什么泛型
                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                // 调用Arrays.toString()方法打印数组内容
                System.out.println(Arrays.toString(actualTypeArguments));
                System.out.println("==========================");
            }
        }
    }
}

class MyTestClass {
    public int i;
    public String str;
    public List list;
    public List<String> stringList;
    public Map map;
    public Map<String, Object> stringObjectMap;
}
/*打印结果:
    [class java.lang.String]
    ==========================
    [class java.lang.String, class java.lang.Object]
    ==========================
 */

Type getRawType()

该方法返回此类型的类或接口的类型。例如List<String>就会返回类型List,而不是尖括号内的泛型String;如Map<String, Object>会返回类型Map。

public class Test {
    public static void main(String[] args) {
        // 创建实体类对象
        MyTestClass myClass = new MyTestClass();
        // 获取Class类对象,然后获取该类中所有声明的字段
        Field[] fields = myClass.getClass().getDeclaredFields();
        // 循环遍历字段数组
        for (Field field : fields) {
            Type genericType = field.getGenericType();
            // 必须是ParameterizedType类型才能做接下来的操作,所以需要先判断
            if (genericType instanceof ParameterizedType) {
                // 首先要强制转型成ParameterizedType类型,才能调用方法
                ParameterizedType parameterizedType = (ParameterizedType) genericType;
                // 调用getRawType方法获取参数化类型变量的原生类型
                Type rawType = parameterizedType.getRawType();
                System.out.println(field.getName() + ": " + rawType);
                System.out.println("==========================");
            }
        }
    }
}

class MyTestClass {
    public int i;
    public String str;
    public List list;
    public List<String> stringList;
    public Map map;
    public Map<String, Object> stringObjectMap;
}
/*打印结果:
    stringList: interface java.util.List
    ==========================
    stringObjectMap: interface java.util.Map
    ==========================
 */

Type getOwnerType()

返回一个Type类型对象,表示该类型所属的类型,必须至少有两个类型。例如,此类型是O<T>.I<S>,则返回O<T>。例如参数化类型Map.Entry<String, Object>类型的变量则会返回Map。

public class Test {
    public static void main(String[] args) {
        // 创建实体类对象
        MyTestClass myClass = new MyTestClass();
        // 获取Class类对象,然后获取该类中所有声明的字段
        Field[] fields = myClass.getClass().getDeclaredFields();
        // 循环遍历字段数组
        for (Field field : fields) {
            Type genericType = field.getGenericType();
            // 必须是ParameterizedType类型才能做接下来的操作,所以需要先判断
            if (genericType instanceof ParameterizedType) {
                // 首先要强制转型成ParameterizedType类型,才能调用方法
                ParameterizedType parameterizedType = (ParameterizedType) genericType;
                // 调用getOwnerType()方法获取此类型所属的类型
                Type ownerType = parameterizedType.getOwnerType();
                System.out.println(field.getName() + ": " + ownerType);
                System.out.println("==========================");
            }
        }
    }
}

class MyTestClass {
    public int i;
    public String str;
    public List list;
    public List<String> stringList;
    public Map map;
    public Map<String, Object> stringObjectMap;
    public Map.Entry<String, Object> mapEntry;
}
/*打印结果:
    stringList: null
    ==========================
    stringObjectMap: null
    ==========================
    mapEntry: interface java.util.Map
    ==========================
 */

参数化类型主要可以用来获取成员变量、方法返回值、方法参数的泛型类型。

参考资料链接:

以上是关于ParameterizedType类的使用的主要内容,如果未能解决你的问题,请参考以下文章

((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]

javajav 通过 反射 获取 泛型信息

怎么取出类的泛型类型

类型转换错误解决方案reflect.ParameterizedType

使用Gson结合泛型解析数据

parameterizedType.getActualTypeArguments()[0]是什么意思?