美文网首页
基于ParameterizedType实现泛型类类型参数化

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

作者: 几行代码 | 来源:发表于2019-02-23 11:48 被阅读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();
}
  • 发现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<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编程语言中所有类型的通用超级接口。这些类型包括原始类型、参数化类型、数组类型、类型变量和基元类型。

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

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

相关文章

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

    在上一篇中我们用到了这个方法: 在这篇中就来分析一下什么是ParameterizedType,它有什么作用。Par...

  • javaSE_day13_泛型

    泛型:参数化数据类型;类,方法 ,构造器,接口 好处:编译器 进行类型检查; 泛型类:类名 <类型参数> 类型参数...

  • 34. 泛型

    泛型即参数化类型。将类型参数化,可以用在类、接口、方法上。泛型类 创建类的实例时,要指定类型的参数。或者赋值让编译...

  • Java并发编程

    Java泛型(类型参数化)接口或者类泛型,类型参数放在接口名或者类名后面方法中的泛型参数放在修饰符public/p...

  • 泛型-学习

    1、什么是泛型?参数化类型, 比如形参,不提前只能参数的类型。可以用在类、接口、方法中分别是泛型类、泛型接口、泛型...

  • 理解2:泛型

    泛型概述 泛型,即“参数化类型”。(将类型从具体设置成参数化)【可应用在类、接口、方法】 泛型概述 泛型只在编译阶...

  • C#规范整理·泛型委托事件

    基于泛型,我们得以将类型参数化,以便更大范围地进行代码复用。同时,它减少了泛型类及泛型方法中的转型,确保了类型安全...

  • C#规范整理·泛型委托事件

    基于泛型,我们得以将类型参数化,以便更大范围地进行代码复用。同时,它减少了泛型类及泛型方法中的转型,确保了类型安全...

  • 泛型 2020-11-16

    泛型 概念 泛型:参数化类型,在不创建新的类型的情况下,通过泛型指定不同的类型来控制形参具体限制的类型。 参数化类...

  • 泛型

    泛型的本质是参数化类型,即将操作数的数据类型指定为一个参数。当这种参数类型用在类中时,就称该类为泛型类。泛型类的格...

网友评论

      本文标题:基于ParameterizedType实现泛型类类型参数化

      本文链接:https://www.haomeiwen.com/subject/gxguyqtx.html