public static < T > Class < ? > getTypeArgument ( final Class < ? extends T > clazz , final TypeVariable < ? extends GenericDeclaration > tv ) { final Map < Type , Type > resolvedTypes = new HashMap < Type , Type > ( ) ; Type type = clazz ; // start walking up the inheritance hierarchy until we hit the end while ( type != null && ! Object . class . equals ( getClass ( type ) ) ) { if ( type instanceof Class ) { // there is no useful information for us in raw types, so just // keep going. 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 ++ ) { if ( typeParameters [ i ] . equals ( tv ) ) { final Class cls = getClass ( actualTypeArguments [ i ] ) ; if ( cls != null ) { return cls ; } //We don't know that the type we want is the one in the map, if this argument has been //passed through multiple levels of the hierarchy. Walk back until we run out. Type typeToTest = resolvedTypes . get ( actualTypeArguments [ i ] ) ; while ( typeToTest != null ) { final Class classToTest = getClass ( typeToTest ) ; if ( classToTest != null ) { return classToTest ; } typeToTest = resolvedTypes . get ( typeToTest ) ; } } resolvedTypes . put ( typeParameters [ i ] , actualTypeArguments [ i ] ) ; } if ( ! rawType . equals ( Object . class ) ) { type = rawType . getGenericSuperclass ( ) ; } } } return null ; }
Returns the type argument