public static < T > Type [ ] resolveActualTypeArgs ( Class < ? extends T > offspring , Class < T > base , Type ... actualArgs ) { if ( offspring == null || base == null || ( actualArgs . length != 0 && actualArgs . length != offspring . getTypeParameters ( ) . length ) ) { throw new IllegalArgumentException ( "offspring and base should not be null, number ot actualArgs should match number of offspring types" ) ; } if ( actualArgs . length == 0 ) { actualArgs = offspring . getTypeParameters ( ) ; } Map < String , Type > typeVariables = new HashMap <> ( ) ; for ( int i = 0 ; i < actualArgs . length ; i ++ ) { TypeVariable < ? > typeVariable = offspring . getTypeParameters ( ) [ i ] ; typeVariables . put ( typeVariable . getName ( ) , actualArgs [ i ] ) ; } List < Type > ancestors = new LinkedList <> ( ) ; if ( offspring . getGenericSuperclass ( ) != null ) { ancestors . add ( offspring . getGenericSuperclass ( ) ) ; } Collections . addAll ( ancestors , offspring . getGenericInterfaces ( ) ) ; for ( Type type : ancestors ) { if ( type instanceof Class < ? > ) { Class < ? > ancestorClass = ( Class < ? > ) type ; if ( base . isAssignableFrom ( ancestorClass ) ) { Type [ ] result = resolveActualTypeArgs ( ( Class < ? extends T > ) ancestorClass , base ) ; if ( result != null ) { return result ; } } } if ( type instanceof ParameterizedType ) { ParameterizedType parameterizedType = ( ParameterizedType ) type ; Type rawType = parameterizedType . getRawType ( ) ; if ( rawType instanceof Class < ? > ) { Class < ? > rawTypeClass = ( Class < ? > ) rawType ; if ( base . isAssignableFrom ( rawTypeClass ) ) { List < Type > resolvedTypes = new LinkedList <> ( ) ; for ( Type t : parameterizedType . getActualTypeArguments ( ) ) { if ( t instanceof TypeVariable < ? > ) { Type resolvedType = typeVariables . get ( ( ( TypeVariable < ? > ) t ) . getName ( ) ) ; resolvedTypes . add ( resolvedType != null ? resolvedType : t ) ; } else { resolvedTypes . add ( t ) ; } } Type [ ] result = resolveActualTypeArgs ( ( Class < ? extends T > ) rawTypeClass , base , resolvedTypes . toArray ( new Type [ ] { } ) ) ; if ( result != null ) { return result ; } } } } } return offspring . equals ( base ) ? actualArgs : new Type [ ] { } ; }
Resolves the actual generic type arguments for a base class as viewed from a subclass or implementation .