code: static <T> List<Class> getTypeArguments(Class<T> baseClass, Class<? extends T> childClass) {
          Map<Type, Type> resolvedTypes = new LinkedHashMap<Type, Type>();
          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<Class> typeArgumentsAsClasses = new ArrayList<Class>();
          // 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;
      }
docs: 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.