基于ParameterizedType实现泛型类类型参数化

2019-02-23  本文已影响0人  几行代码

在上一篇中我们用到了这个方法:

public static <T> T getInstance(Object object, int i) {
        if (object != null) {
            return (T) ((ParameterizedType) object.getClass()
                    .getGenericSuperclass())
                    .getActualTypeArguments()[i];
        }
        return null;
    }

在这篇中就来分析一下什么是ParameterizedType,它有什么作用。
ParameterizedType是 JDK7 开始, java.lang.reflect 提供了Interface ParameterizedType. 通过实现这个接口, 我们可以实现泛型类的类型的参数化。
先来看看它的源码:

/**
 * ParameterizedType represents a parameterized type such as
 * Collection&lt;String&gt;.
 *
 * <p>A parameterized type is created the first time it is needed by a
 * reflective method, as specified in this package. When a
 * parameterized type p is created, the generic type declaration that
 * p instantiates is resolved, and all type arguments of p are created
 * recursively. See {@link java.lang.reflect.TypeVariable
 * TypeVariable} for details on the creation process for type
 * variables. Repeated creation of a parameterized type has no effect.
 *
 * <p>Instances of classes that implement this interface must implement
 * an equals() method that equates any two instances that share the
 * same generic type declaration and have equal type parameters.
 *
 * @since 1.5
 */
public interface ParameterizedType extends Type {
    /**
     * Returns an array of {@code Type} objects representing the actual type
     * arguments to this type.
     *
     * <p>Note that in some cases, the returned array be empty. This can occur
     * if this type represents a non-parameterized type nested within
     * a parameterized type.
     *
     * @return an array of {@code Type} objects representing the actual type
     *     arguments to this type
     * @throws TypeNotPresentException if any of the
     *     actual type arguments refers to a non-existent type declaration
     * @throws MalformedParameterizedTypeException if any of the
     *     actual type parameters refer to a parameterized type that cannot
     *     be instantiated for any reason
     * @since 1.5
     */
    Type[] getActualTypeArguments();

    /**
     * Returns the {@code Type} object representing the class or interface
     * that declared this type.
     *
     * @return the {@code Type} object representing the class or interface
     *     that declared this type
     * @since 1.5
     */
    Type getRawType();

    /**
     * Returns a {@code Type} object representing the type that this type
     * is a member of.  For example, if this type is {@code O<T>.I<S>},
     * return a representation of {@code O<T>}.
     *
     * <p>If this type is a top-level type, {@code null} is returned.
     *
     * @return a {@code Type} object representing the type that
     *     this type is a member of. If this type is a top-level type,
     *     {@code null} is returned
     * @throws TypeNotPresentException if the owner type
     *     refers to a non-existent type declaration
     * @throws MalformedParameterizedTypeException if the owner type
     *     refers to a parameterized type that cannot be instantiated
     *     for any reason
     * @since 1.5
     */
    Type getOwnerType();
}
/**
 * Type is the common superinterface for all types in the Java
 * programming language. These include raw types, parameterized types,
 * array types, type variables and primitive types.
 *
 * @since 1.5
 */
public interface Type {
    /**
     * Returns a string describing this type, including information
     * about any type parameters.
     *
     * @implSpec The default implementation calls {@code toString}.
     *
     * @return a string describing this type
     * @since 1.8
     */
    default String getTypeName() {
        return toString();
    }
}

这是官方的注释:

Type is the common superinterface for all types in the Java programming language. These include raw types, parameterized types, array types, type variables and primitive types.
Type 是Java编程语言中所有类型的通用超级接口。这些类型包括原始类型、参数化类型、数组类型、类型变量和基元类型。
这里解释的很清楚了,Type接口是Java编程语言中所有类型的通用超级接口。

下面我们继续看ParameterizedType:

A parameterized type is created the first time it is needed by a reflective method, as specified in this package. When a parameterized type p is created, the generic type declaration that p instantiates is resolved, and all type arguments of p are created
recursively. See {@link java.lang.reflect.TypeVariable TypeVariable} for details on the creation process for type variables.
Repeated creation of a parameterized type has no effect.

大概意思是说:ParameterizedType是在反射方法第一次需要时创建的,如包中指定的。当创建参数化类型p时,解析p实例化的泛型类型声明,并且递归地创建p的所有类型参数。有关类型变量创建过程的详细信息,请参见@link java.lang.reflect.typevariable typevariable。
重复创建参数化类型没有效果。

怎么来判断参数化类型呢?
通过下面例子来说明

public class ParameterizedTypeBean {
    List<String> listString;
    List list;
    Map<String,Long> mapString;
    Map map;
    Map.Entry<Long,Short> mapLong;
}

测试:

Field[] declaredFields = ParameterizedTypeBean.class.getDeclaredFields(); // 反射获取字段
        for (Field field : declaredFields) {
            // 是否是 ParameterizedType 参数化类型
            System.out.println(field.getName() + ": " + (field.getGenericType() instanceof ParameterizedType));
        }

结果打印:

listString: true
list: false
mapString: true
map: false
mapLong: true

从打印结果看来,具有<>(泛型)符号的变量是参数化类型。

我们分别来看ParameterizedType内部的三个方法:

该方法返回一个Type数组
Type[] getActualTypeArguments();

测试代码:

Field[] declaredFields = ParameterizedTypeBean.class.getDeclaredFields(); // 反射获取字段
        for (Field field : declaredFields) {
            if (field.getGenericType() instanceof ParameterizedType) {

                ParameterizedType genericType = (ParameterizedType) field.getGenericType();

                System.out.print("变量类型 = " + genericType.getTypeName() + "   ");
                System.out.print("变量名称 = " + field.getName() + "   ");

                // 泛型类型的数组
                Type[] actualTypeArguments = genericType.getActualTypeArguments();

                for (Type type: actualTypeArguments) {
                    System.out.print("泛型类型 = " + type.getTypeName()  + "   ");
                }
                System.out.println();
                System.out.println();
            }
        }

打印结果:

变量类型 = java.util.List<java.lang.String>   变量名称 = listString   泛型类型 = java.lang.String   

变量类型 = java.util.Map<java.lang.String, java.lang.Long>   变量名称 = mapString   泛型类型 = java.lang.String   泛型类型 = java.lang.Long   

变量类型 = java.util.Map$Entry<java.lang.Long, java.lang.Short>   变量名称 = mapLong   泛型类型 = java.lang.Long   泛型类型 = java.lang.Short   

ps: 从打印结果返回来看,getActualTypeArguments()返回了一个Type数组,数组里是参数化类型的参数。

Type getRawType();

测试代码:

Field[] declaredFields = ParameterizedTypeBean.class.getDeclaredFields(); // 反射获取字段
        for (Field field : declaredFields) {
            if (field.getGenericType() instanceof ParameterizedType) {

                ParameterizedType genericType = (ParameterizedType) field.getGenericType();

                System.out.print("变量 名称= " + field.getName() + "   ");

                // 获取变量的类型 genericType.getRawType()
                System.out.print("getRawType() = " + genericType.getRawType().getTypeName());

                System.out.println();
                System.out.println();
            }
        }

打印结果:

变量 名称= listString   getRawType() = java.util.List

变量 名称= mapString   getRawType() = java.util.Map

变量 名称= mapLong   getRawType() = java.util.Map$Entry

PS:从打印结果来看,getRawType()是变量的类型

Type getOwnerType();

测试代码:

Field[] declaredFields = ParameterizedTypeBean.class.getDeclaredFields(); // 反射获取字段
        for (Field field : declaredFields) {
            if (field.getGenericType() instanceof ParameterizedType) {
                ParameterizedType genericType = (ParameterizedType) field.getGenericType();

                System.out.print("变量 名称= " + field.getName() + "   ");

                Type ownerType = genericType.getOwnerType();
                if (ownerType != null) {
                    System.out.print("getOwnerType() = " + ownerType.getTypeName());
                } else {
                    System.out.print("getOwnerType() = null");
                }

                System.out.println();
                System.out.println();
            }
        }

打印结果:

变量 名称= listString   getOwnerType() = null

变量 名称= mapString   getOwnerType() = null

变量 名称= mapLong   getOwnerType() = java.util.Map

PS:从打印结果来看,前面两个都为null,最后一个为Map类型

前两个为什么会返回 null 呢。看一下官网的注释:

Returns a {@code Type} object representing the type that this type is a member of. For example, if this type is {@code O<T>.I<S>}, return a representation of {@code O<T>}.

大概意思是说:返回@code type对象,该对象表示此类型所属的类型。例如,如果此类型为@code o<t>.i<s>,则返回@code o<t>的表示形式。
也就是说:

O<T>.I<S>类型的变量,调用getOwnerType()会返回O<T>

官网还有一句:

If this type is a top-level type, {@code null} is returned.
如果此类型是顶级类型,则返回@code null。

这就解释为什么会打印 null 了。

总结:

1.Type 是Java编程语言中所有类型的通用超级接口。这些类型包括原始类型、参数化类型、数组类型、类型变量和基元类型。

2.只有具有<>(泛型)符号的变量是参数化类型。
3.getActualTypeArguments()返回了一个Type数组,数组里是参数化类型的参数,可以根据这个方法获取到 “泛型的类型”。
4.getRawType()是获取变量的类型。
5.getOwnerType()方法对于O<T>.I<S>类型的变量,会返回O<T>,例如:Map.Entry<Long,Short> mapLong,会返回java.util.Map,而不是java.util.Entry。

基于ParameterizedType获取泛型参数类型的实例:https://www.jianshu.com/p/5a7f36c7dd9e

上一篇 下一篇

猜你喜欢

热点阅读