public static Type resolveTypeVariableType(Class<?> concreteClass, TypeVariable<?> typeVariable) {
        Class<?> classThatContainsTypeVariable = getClassThatContainsTypeVariable(typeVariable);

        // If the type variable is defined in the concrete class, we can only use the bounds
        if (concreteClass == classThatContainsTypeVariable) {
            return resolve(concreteClass, typeVariable.getBounds()[0]);
        }
        if (!isSubtype(concreteClass, classThatContainsTypeVariable)) {
            throw new IllegalArgumentException(
                    "The given concrete class is not a subtype of the class that contain the type variable!");
        }

        int position = getTypeVariablePosition(typeVariable);

        if (position == -1) {
            // Should never happen
            throw new IllegalArgumentException(
                    "Type variable not found in its container class!");
        }

        Set<Class<?>> superTypes = getSuperTypes(concreteClass, classThatContainsTypeVariable);
        List<Class<?>> classStack = new ArrayList<>(superTypes.size());
        Type resolvedType = typeVariable;

        // The class that contains the type variable mustn't be considered
        superTypes.remove(classThatContainsTypeVariable);
        // Build a stack of the class hierarchy to be able to resolve the type
        classStack.addAll(superTypes);

        // Resolve every type variable in every class level
        // We need to do this here because the type variables of subclasses
        // of the container class of the type variable could move their
        // type variables to different positions
        while (!classStack.isEmpty() && !(resolvedType instanceof Class<?>)) {
            // Start at most general type and go down the hierarchy until
            // we reach concreteClass. Resolve the current type variable
            // to every level of the hierarchy and stop as soon as the
            // type is instance of java.lang.Class
            Class<?> classToInspect = classStack.remove(classStack.size() - 1);
            Type[] genericInterfaces = classToInspect.getGenericInterfaces();
            List<Type> typesToInspect = new ArrayList<Type>(genericInterfaces.length + 1);
            typesToInspect.add(classToInspect.getGenericSuperclass());
            Collections.addAll(typesToInspect, genericInterfaces);

            for (Type classToInspectType : typesToInspect) {
                // Since the resolvedType is not yet instance of class, the
                // classToInspectType has to be a ParameterizedType
                // otherwise we can not resolve the type variable
                if (!(classToInspectType instanceof ParameterizedType)) {
                    continue;
                }

                ParameterizedType parameterizedClassToInspect = (ParameterizedType) classToInspectType;

                // The found parameterized type is not the one we are looking for
                if (!classThatContainsTypeVariable.equals(parameterizedClassToInspect.getRawType())) {
                    continue;
                }

                // This should be fulfilled, anyway we check it
                if (parameterizedClassToInspect.getActualTypeArguments().length < position + 1) {
                    throw new IllegalArgumentException("Could not resolve type");
                }

                // Set the type of the type arguments at the needed position
                // as the resolvedType
                resolvedType = parameterizedClassToInspect.getActualTypeArguments()[position];

                if (resolvedType instanceof TypeVariable<?>) {
                    // If the currently available resolvedType is still a type
                    // variable
                    // retrieve the position of the type variable within the type
                    // variables of the current class, so we can look in the next
                    // subclass for the concrete type

                    position = getTypeVariablePosition(classToInspect,
                            (TypeVariable<?>) resolvedType);
                    classThatContainsTypeVariable = getClassThatContainsTypeVariable((TypeVariable<?>) resolvedType);
                    break;
                } else if (resolvedType instanceof ParameterizedType) {
                    // Since we only want a class object, we don't
                    // care about type arguments of the parameterized type
                    // and just set the raw type of it as the resolved
                    // type
                    resolvedType = ((ParameterizedType) resolvedType).getRawType();
                    break;
                } else if (resolvedType instanceof WildcardType) {
                    WildcardType wildcardType = ((WildcardType) resolvedType);

                    if (wildcardType.getLowerBounds().length > 0) {
                        resolvedType = resolveType(concreteClass, wildcardType.getLowerBounds()[0]);
                    } else {
                        resolvedType = resolveType(concreteClass, wildcardType.getUpperBounds()[0]);
                    }
                    break;
                } else if (resolvedType instanceof Class<?>) {
                    break;
                }
            }
        }

        return resolvedType;
    }
public static Type resolveTypeVariableType ( Class < ? > concreteClass , TypeVariable < ? > typeVariable ) { Class < ? > classThatContainsTypeVariable = getClassThatContainsTypeVariable ( typeVariable ) ; if ( concreteClass == classThatContainsTypeVariable ) { return resolve ( concreteClass , typeVariable . getBounds ( ) [ 0 ] ) ; } if ( ! isSubtype ( concreteClass , classThatContainsTypeVariable ) ) { throw new IllegalArgumentException ( "The given concrete class is not a subtype of the class that contain the type variable!" ) ; } int position = getTypeVariablePosition ( typeVariable ) ; if ( position == - 1 ) { throw new IllegalArgumentException ( "Type variable not found in its container class!" ) ; } Set < Class < ? > > superTypes = getSuperTypes ( concreteClass , classThatContainsTypeVariable ) ; List < Class < ? > > classStack = new ArrayList < > ( superTypes . size ( ) ) ; Type resolvedType = typeVariable ; superTypes . remove ( classThatContainsTypeVariable ) ; classStack . addAll ( superTypes ) ; while ( ! classStack . isEmpty ( ) && ! ( resolvedType instanceof Class < ? > ) ) { Class < ? > classToInspect = classStack . remove ( classStack . size ( ) - 1 ) ; Type [ ] genericInterfaces = classToInspect . getGenericInterfaces ( ) ; List < Type > typesToInspect = new ArrayList < Type > ( genericInterfaces . length + 1 ) ; typesToInspect . add ( classToInspect . getGenericSuperclass ( ) ) ; Collections . addAll ( typesToInspect , genericInterfaces ) ; for ( Type classToInspectType : typesToInspect ) { if ( ! ( classToInspectType instanceof ParameterizedType ) ) { continue ; } ParameterizedType parameterizedClassToInspect = ( ParameterizedType ) classToInspectType ; if ( ! classThatContainsTypeVariable . equals ( parameterizedClassToInspect . getRawType ( ) ) ) { continue ; } if ( parameterizedClassToInspect . getActualTypeArguments ( ) . length < position + 1 ) { throw new IllegalArgumentException ( "Could not resolve type" ) ; } resolvedType = parameterizedClassToInspect . getActualTypeArguments ( ) [ position ] ; if ( resolvedType instanceof TypeVariable < ? > ) { position = getTypeVariablePosition ( classToInspect , ( TypeVariable < ? > ) resolvedType ) ; classThatContainsTypeVariable = getClassThatContainsTypeVariable ( ( TypeVariable < ? > ) resolvedType ) ; break ; } else if ( resolvedType instanceof ParameterizedType ) { resolvedType = ( ( ParameterizedType ) resolvedType ) . getRawType ( ) ; break ; } else if ( resolvedType instanceof WildcardType ) { WildcardType wildcardType = ( ( WildcardType ) resolvedType ) ; if ( wildcardType . getLowerBounds ( ) . length > 0 ) { resolvedType = resolveType ( concreteClass , wildcardType . getLowerBounds ( ) [ 0 ] ) ; } else { resolvedType = resolveType ( concreteClass , wildcardType . getUpperBounds ( ) [ 0 ] ) ; } break ; } else if ( resolvedType instanceof Class < ? > ) { break ; } } } return resolvedType ; }
Tries to resolve the type variable against the concrete class. The
concrete class has to be a subtype of the type in which the type variable
has been declared. This method tries to resolve the given type variable
by inspecting the subclasses of the class in which the type variable was
declared and as soon as the resolved type is instance of java.lang.Class
it stops and returns that class.

@param concreteClass The class which is used to resolve the type. The type for the
type variable must be bound in this class or a superclass.
@param typeVariable  The type variable to resolve.
@return The resolved type
@throws IllegalArgumentException Is thrown when the concrete class is not a subtype of the
class in which the type variable has been declared.