Get generic type of class at runtime

后端 未结 26 2511
野的像风
野的像风 2020-11-21 04:40

How can I achieve this?

public class GenericClass
{
    public Type getMyType()
    {
        //How do I return the type of T?
    }
}
26条回答
  •  走了就别回头了
    2020-11-21 05:05

    Technique described in this article by Ian Robertson works for me.

    In short quick and dirty example:

     public abstract class AbstractDAO
     {
        /**
         * Method returns class implementing EntityInterface which was used in class
         * extending AbstractDAO
         *
         * @return Class
         */
        public Class returnedClass()
        {
            return (Class) getTypeArguments(AbstractDAO.class, getClass()).get(0);
        }
    
        /**
         * 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(Type type)
        {
            if (type instanceof Class) {
                return (Class) type;
            } else if (type instanceof ParameterizedType) {
                return getClass(((ParameterizedType) type).getRawType());
            } else if (type instanceof GenericArrayType) {
                Type componentType = ((GenericArrayType) type).getGenericComponentType();
                Class componentClass = getClass(componentType);
                if (componentClass != null) {
                    return Array.newInstance(componentClass, 0).getClass();
                } else {
                    return null;
                }
            } else {
                return null;
            }
        }
    
        /**
         * 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  List> getTypeArguments(
                Class baseClass, Class childClass)
        {
            Map resolvedTypes = new HashMap();
            Type type = childClass;
            // start walking up the inheritance hierarchy until we hit baseClass
            while (!getClass(type).equals(baseClass)) {
                if (type instanceof Class) {
                    // there is no useful information for us in raw types, so just keep going.
                    type = ((Class) type).getGenericSuperclass();
                } else {
                    ParameterizedType parameterizedType = (ParameterizedType) type;
                    Class rawType = (Class) parameterizedType.getRawType();
    
                    Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                    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();
            }
            List> typeArgumentsAsClasses = new ArrayList>();
            // 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;
        }
      }
    

提交回复
热议问题