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

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

public static  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<String>.
 *
 * 

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. * *

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. * *

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.I}, * return a representation of {@code O}. * *

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(); }

  • 发现ParameterizedType是一个接口,并继承Type这个对象,Type是什么呢我们点进去也看看:
/**
 * 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 listString;
    List list;
    Map mapString;
    Map map;
    Map.Entry 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   变量名称 = listString   泛型类型 = java.lang.String   

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

变量类型 = java.util.Map$Entry   变量名称 = 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.I}, return a representation of {@code O}.

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

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

官网还有一句:

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

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

总结:

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

  • 内部的 getTypeName() 方法会返回对应类型的全限定类名。

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

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

你可能感兴趣的:(基于ParameterizedType实现泛型类类型参数化)