集册 Java实例教程 获取子类用于扩展通用基类的实际类型参数。

获取子类用于扩展通用基类的实际类型参数。

欢马劈雪     最近更新时间:2020-01-02 10:19:05

529
获取子类用于扩展通用基类的实际类型参数。


//package com.nowjava;

import java.lang.reflect.*;

import java.util.ArrayList;
/* 
*来 自
 时 代 J a v a 公 众 号
*/

import java.util.HashMap;

import java.util.List;

import java.util.Map;


public class Main {

    /**

     * Get the actual type arguments a child class has used to extend a generic

     * base class.

     * 

     * @param baseClass

     *            the base class

     * @param childClass

     *            the child class

     * @return a list of the raw classes for the actual type arguments.

     */

    public static <T> List<Class<?>> getTypeArguments(

            final Class<T> baseClass, final Class<? extends T> childClass) {
            /** 
            来 自 
            n o w j a v a . c o m - 时  代  Java
            **/

        final Map<Type, Type> resolvedTypes = new HashMap<Type, Type>();

        Type type = childClass;

        // start walking up the inheritance hierarchy until we hit baseClass

        while (!getClass(type).equals(baseClass))

            if (type instanceof Class)

                type = ((Class<?>) type).getGenericSuperclass();

            else {

                final ParameterizedType parameterizedType = (ParameterizedType) type;

                final Class<?> rawType = (Class<?>) parameterizedType

                        .getRawType();


                final Type[] actualTypeArguments = parameterizedType

                        .getActualTypeArguments();

                final TypeVariable<?>[] typeParameters = rawType

                        .getTypeParameters();

                for (int i = 0; i < actualTypeArguments.length; i++)

                    resolvedTypes.put(typeParameters[i],

                            actualTypeArguments[i]);


                if (!rawType.equals(baseClass))

                    type = rawType.getGenericSuperclass();

            }


        // finally, for each actual type argument provided to baseClass, determine (if possible)

        // the raw class for that type argument.

        Type[] actualTypeArguments;

        if (type instanceof Class)

            actualTypeArguments = ((Class<?>) type).getTypeParameters();

        else

            actualTypeArguments = ((ParameterizedType) type)

                    .getActualTypeArguments();

        final List<Class<?>> typeArgumentsAsClasses = new ArrayList<Class<?>>();

        // resolve types by chasing down type variables.

        for (Type baseType : actualTypeArguments) {

            while (resolvedTypes.containsKey(baseType))

                baseType = resolvedTypes.get(baseType);

            typeArgumentsAsClasses.add(getClass(baseType));

        }

        return typeArgumentsAsClasses;

    }


    /**

     * Get the underlying class for a type, or null if the type is a variable

     * type.

     * 

     * @param type

     *            the type

     * @return the underlying class

     */

    public static Class<?> getClass(final Type type) {

        if (type instanceof Class)

            return (Class<?>) type;

        else if (type instanceof ParameterizedType)

            
展开阅读全文