When a generic type information is required at runtime, it has to be passed in:
public class GenericClass<T> { 
     private final Class<T> type; 
     public GenericClass(Class<T> type) { 
          this.type = type; 
     } 
     public Class<T> getMyType() { 
         return this.type; 
     } 
} 
 | 
e.g. The following parameter information is available:
- the field parameters of its generic declaration by using: field.getGenericType()
 - the parameter declared in the return generic type by using: method.getGenericReturnType()
 - the parameter declared against all the method parameters by using: method.getGenericParameterTypes
 
public class GenericReflection
  { 
       public static class B { 
             private A<String,
  Integer> a; 
             public A<String,
  Integer> get(final List<String> ls, final List<Integer> li) { 
                    a = new A<String,
  Integer>(ls.get(0), li.get(0)); 
                    return a; 
             } 
       } 
       public static class A<U, V> { 
             private final U u; 
             private final V v; 
             public A(final U u, V v) { 
                    this.u = u; 
                    this.v = v; 
             } 
             @A1 
             public U getU() { 
                    return u; 
             } 
             public V getV() { 
                    return v; 
             } 
       } 
       public static class IndexedType { 
             public int getIndex() { 
                    return index; 
             } 
             public Class<?>
  getType() { 
                    return type; 
             } 
             private final int index; 
             private final Class<?> type; 
             public IndexedType(final int index, final Class<?> type) { 
                    this.index = index; 
                    this.type = type; 
             } 
             @Override 
             public int hashCode() { 
                    final int prime = 31; 
                    int result = 1; 
                    result = prime * result + index; 
                    result = prime * result + ((type == null) ? 0 : type.hashCode()); 
                    return result; 
             } 
             @Override 
             public boolean equals(Object obj) { 
                    if (this == obj) 
                           return true; 
                    if (obj == null) 
                           return false; 
                    if (getClass() != obj.getClass()) 
                           return false; 
                    IndexedType other = (IndexedType) obj; 
                    if (index != other.index) 
                           return false; 
                    if (type == null) { 
                           if (other.type != null) 
                                 return false; 
                    } else if (!type.equals(other.type)) 
                           return false; 
                    return true; 
             } 
             @Override 
             public String toString()
  { 
                    return "IndexedType
  [index=" + index + ", type=" + type + "]"; 
             } 
       } 
       @Test 
       public void test() throws
  NoSuchMethodException, SecurityException, NoSuchFieldException { 
             System.out.println("===test==="); 
             final B b = new B(); 
             Map<IndexedType,
  List<Class<?>>> parameterizedReturnTypeMap = getParameterizedReturnTypes(b, "get", List.class, List.class); 
             System.out.println("returnParameterTypes:" + parameterizedReturnTypeMap); 
             Map<IndexedType,
  List<Class<?>>> parameterizedParameterTypeMap = getParameterizedParameterMap(b, "get", List.class, 
                           List.class); 
             System.out.println("parameterParametersMap:" + parameterizedParameterTypeMap); 
             Map<IndexedType,
  List<Class<?>>> parameterizedFieldArgumentTypeMap = getParameterizedFieldArgumentTypeMap(b, "a"); 
             System.out.println("fieldArgTypeList:" + parameterizedFieldArgumentTypeMap); 
       } 
       public static
  Map<IndexedType, List<Class<?>>>
  getParameterizedReturnTypes(Object obj, String methodName, Class<?>...
  parameterTypes) 
                    throws
  NoSuchMethodException, SecurityException { 
             final Method method = obj.getClass().getMethod(methodName, parameterTypes); 
             final Type genericReturnType = method.getGenericReturnType(); 
             final Type[] genericTypes = new Type[]{genericReturnType}; 
             final
  Map<IndexedType, List<Class<?>>> parameterizedTypeMap = getParameterizedTypeMap(genericTypes); 
             return parameterizedTypeMap; 
       } 
       public static
  Map<IndexedType, List<Class<?>>>
  getParameterizedParameterMap(Object obj, String methodName, 
                    Class<?>... parameterTypes) throws
  NoSuchMethodException, SecurityException { 
             Method method = obj.getClass().getMethod(methodName, parameterTypes); 
             Type[] genericTypes = method.getGenericParameterTypes(); 
             final
  Map<IndexedType, List<Class<?>>> parameterizedTypeMap = getParameterizedTypeMap(genericTypes); 
             return parameterizedTypeMap; 
       } 
       public static
  Map<IndexedType, List<Class<?>>>
  getParameterizedFieldArgumentTypeMap(Object obj, String fieldName) throws NoSuchFieldException,
  SecurityException { 
             final Field field = obj.getClass().getDeclaredField(fieldName); 
             final Type genericFieldType = field.getGenericType(); 
             final Type[] genericTypes = new Type[]{genericFieldType}; 
             final
  Map<IndexedType, List<Class<?>>> parameterizedTypeMap = getParameterizedTypeMap(genericTypes); 
             return parameterizedTypeMap; 
       } 
       private static
  Map<IndexedType, List<Class<?>>>
  getParameterizedTypeMap(Type[] genericTypes) { 
             final
  Map<IndexedType, List<Class<?>>> parameterizedTypeMap = new HashMap<>(); 
             int index = 0; 
             for (Type genericType : genericTypes) { 
                    if (genericType instanceof ParameterizedType)
  { 
                           ParameterizedType aParameterizedType =
  (ParameterizedType) genericType; 
                           final
  List<Class<?>> actualTypeArgumentClassList = new
  ArrayList<>(); 
                           Class<?> aParameterizedTypeClass = (Class<?>)
  aParameterizedType.getRawType(); 
                           parameterizedTypeMap.put(new IndexedType(index++, aParameterizedTypeClass), actualTypeArgumentClassList); 
                           Type[] actualTypeArguments = aParameterizedType.getActualTypeArguments(); 
                           for (Type typeArgument : actualTypeArguments) { 
                                 Class<?>
  actualTypeArgumentClass = (Class<?>)
  typeArgument; 
                                  actualTypeArgumentClassList.add(actualTypeArgumentClass); 
                           } 
                    } 
             } 
             return parameterizedTypeMap; 
       } 
       @Test 
       public void
  testTypeSafeCache() { 
             System.out.println("===testTypeSafeCache==="); 
             final TypeSafeCache cache = new TypeSafeCache(); 
             cache.put(Integer.class, 1); 
             cache.put(Long.class, 1L); 
             cache.put(Double.class, 1.0); 
             System.out.println(cache.get(Integer.class)); 
             System.out.println(cache.get(Long.class)); 
             System.out.println(cache.get(Double.class)); 
       } 
       @Test 
       public void
  testTypeSafeAnnotationType() throws NoSuchMethodException,
  SecurityException { 
             System.out.println("===testTypeSafeAnnotationType==="); 
             final A<String,
  Integer> a = new A<>("A", 1); 
             Method method = a.getClass().getMethod("getU"); 
             System.out.println("method" + method); 
             Annotation a1 = method.getAnnotation(A1.class); 
             System.out.println("annotationType:" + a1.annotationType()); 
             System.out.println("annotationType().getCanonicalName():" + a1.annotationType().getCanonicalName()); 
             System.out.println( 
                           "annotationType().getClass().getCanonicalName():" + a1.annotationType().getClass().getCanonicalName()); 
             System.out.println(".annotationType().getTypeName():" + a1.annotationType().getTypeName()); 
             System.out.println(".annotationType().getGenericSuperclass():" + a1.annotationType().getGenericSuperclass()); 
             Annotation result = getAnnotation(method, a1.annotationType().getTypeName()); 
             System.out.println("result:" + result); 
       } 
} 
 | 
 
===testTypeSafeCache=== 
1 
1 
1.0 
===test=== 
returnParameterTypes:{IndexedType
  [index=0, type=class
  com.americanexpress.ssae.sample.generic.GenericReflection$A]=[class
  java.lang.String, class java.lang.Integer]} 
parameterParametersMap:{IndexedType
  [index=0, type=interface java.util.List]=[class java.lang.String], IndexedType
  [index=1, type=interface java.util.List]=[class java.lang.Integer]} 
===testTypeSafeAnnotationType=== 
method:public
  java.lang.Object
  com.americanexpress.ssae.sample.generic.GenericReflection$A.getU() 
annotationType:interface
  com.americanexpress.ssae.sample.generic.GenericReflection$A1 
annotationType().getCanonicalName():com.americanexpress.ssae.sample.generic.GenericReflection.A1 
annotationType().getClass().getCanonicalName():java.lang.Class 
.annotationType().getTypeName():com.americanexpress.ssae.sample.generic.GenericReflection$A1 
.annotationType().getGenericSuperclass():null 
annotationType:interface
  com.americanexpress.ssae.sample.generic.GenericReflection$A1 
result:@com.americanexpress.ssae.sample.generic.GenericReflection$A1() 
 |