code: public static Type[] getTypeArguments(Class<?> cls, String... typeParameters) {
  		int requestedParams = typeParameters.length;
  		Type[] types = new Type[requestedParams];
  		int remaining = requestedParams;
  		while (cls != Object.class) {
  			Class<?> parent = cls.getSuperclass();
  			Type parentType = cls.getGenericSuperclass();
  			if (parentType instanceof ParameterizedType) {
  				Type[] args = ((ParameterizedType) parentType).getActualTypeArguments();
  				TypeVariable<?>[] params = parent.getTypeParameters();
  				for (int i = 0, parentParams = params.length; i < parentParams; i++) {
  					String name = params[i].getName();
  					for (int j = 0; j < requestedParams; j++) { // matches any of the requested?
  						if (types[j] == null && typeParameters[j].equals(name)) {
  							types[j] = args[i];
  							if (--remaining > 0) {
  								break;
  							} else {
  								return types;
  							}
  						}
  					}
  				}
  			}
  			cls = parent;
  		}
  		return types;
  	}
docs: <p>
  Get the Types that have been specified by the class or its ancestors for the generic type
  parameters. For example:
  </p>
  <pre>{@code
  class IntStringMap extends HashMap<Integer, String>
  
  Classes.getTypeArguments(IntStringMap.class, "K", "V")
  // returns: [class java.lang.Integer, class java.lang.String]
  }</pre>
  
  @return null elements for any type parameters that weren't found