Obtains a declared method.

@param type     The type
@param argTypes The argument types
@param <T>      The generic type
@return The method
195242
public static <T> Optional<Constructor<T>> findConstructor(Class<T> type, Class... argTypes) {
        try {
            return Optional.of(type.getDeclaredConstructor(argTypes));
        } catch (NoSuchMethodException e) {
            return Optional.empty();
        }
    }
252508
public static Method getMethod(Class<?> cls, String methodName, Class<?>... types) {
        try {
            return cls.getMethod(methodName, types);
        } catch (Exception e) {
            return null;
        }
    }
1124729
Type resolveTypeVariables(final Type type) {
        if (type instanceof Class<?>) {
            // Arrays and non-generic classes have no type variables
            return type;

        } else if (type instanceof ParameterizedType) {
            // Recursively resolve parameterized types
            final ParameterizedType parameterizedType = (ParameterizedType) type;
            final Type[] typeArgs = parameterizedType.getActualTypeArguments();
            Type[] typeArgsResolved = null;
            for (int i = 0; i < typeArgs.length; i++) {
                // Recursively revolve each parameter of the type
                final Type typeArgResolved = resolveTypeVariables(typeArgs[i]);
                // Only compare typeArgs to typeArgResolved until the first difference is found
                if (typeArgsResolved == null) {
                    if (!typeArgResolved.equals(typeArgs[i])) {
                        // After the first difference is found, lazily allocate typeArgsResolved 
                        typeArgsResolved = new Type[typeArgs.length];
                        // Go back and copy all the previous args
                        System.arraycopy(typeArgs, 0, typeArgsResolved, 0, i);
                        // Insert the first different arg
                        typeArgsResolved[i] = typeArgResolved;
                    }
                } else {
                    // After the first difference is found, keep copying the resolved args into the array 
                    typeArgsResolved[i] = typeArgResolved;
                }
            }
            if (typeArgsResolved == null) {
                // There were no type parameters to resolve
                return type;
            } else {
                // Return new ParameterizedType that wraps the resolved type args
                return new ParameterizedTypeImpl((Class<?>) parameterizedType.getRawType(), typeArgsResolved,
                        parameterizedType.getOwnerType());
            }

        } else if (type instanceof TypeVariable<?>) {
            // Look up concrete type for type variable
            final TypeVariable<?> typeVariable = (TypeVariable<?>) type;
            for (int i = 0; i < typeVariables.length; i++) {
                if (typeVariables[i].getName().equals(typeVariable.getName())) {
                    return resolvedTypeArguments[i];
                }
            }
            // Could not resolve type variable
            return type;

        } else if (type instanceof GenericArrayType) {
            // Count the array dimensions, and resolve the innermost type of the array
            int numArrayDims = 0;
            Type t = type;
            while (t instanceof GenericArrayType) {
                numArrayDims++;
                t = ((GenericArrayType) t).getGenericComponentType();
            }
            final Type innermostType = t;
            final Type innermostTypeResolved = resolveTypeVariables(innermostType);
            if (!(innermostTypeResolved instanceof Class<?>)) {
                throw new IllegalArgumentException("Could not resolve generic array type " + type);
            }
            final Class<?> innermostTypeResolvedClass = (Class<?>) innermostTypeResolved;

            // Build an array to hold the size of each dimension, filled with zeroes
            final int[] dims = (int[]) Array.newInstance(int.class, numArrayDims);

            // Build a zero-sized array of the required number of dimensions, using the resolved innermost class 
            final Object arrayInstance = Array.newInstance(innermostTypeResolvedClass, dims);

            // Get the class of this array instance -- this is the resolved array type
            return arrayInstance.getClass();

        } else if (type instanceof WildcardType) {
            // TODO: Support WildcardType
            throw ClassGraphException.newClassGraphException("WildcardType not yet supported: " + type);

        } else {
            throw ClassGraphException.newClassGraphException("Got unexpected type: " + type);
        }
    }
1196021
@Override
    public GenericsContext type(final Class<?> type) {
        return type == currentType ? this : new GenericsContext(genericsInfo, type, root);
    }
1360358
private static Class<?> getActualRawType(Type type) {
        Class<?> rawType;
        if (type instanceof ParameterizedType) {
            rawType = (Class<?>) ((ParameterizedType) type).getRawType();
        } else {
            rawType = (Class<?>) type;
        }
        return rawType;
    }
414304
protected final List<Parameter> getParameters(Type type, List<Annotation> annotations) {
        return getParameters(type, annotations, typesToSkip);
    }
270224
public Signature argType(int index, Class<?> type) {
        return new Signature(type().changeParameterType(index, type), argNames());
    }
829801
public static Class[] getTypes(Object... args) {
      if (args.length == 0) {
         return new Class[0];
      }
      Class[] types = new Class[args.length];
      for (int i = 0; i < args.length; i++) {
         types[i] = args[i] == null ? Object.class : args[i].getClass();
      }
      return types;
   }
20042
public static Class<?>[] getTypes( Object[] args )
    {
        if ( args == null )
            return Reflect.ZERO_TYPES;

        Class<?>[] types = new Class[ args.length ];

        for( int i=0; i < args.length; i++ )
            types[i] = getType(args[i]);

        return types;
    }
933675
@SuppressWarnings("unckecked")
    public static Class<?> getRawType(Type type) {
        if (type instanceof Class<?>) {
            // type is a normal class.
            return (Class<?>) type;

        } else if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;

            // I'm not exactly sure why getRawType() returns Type instead of Class.
            // Neal isn't either but suspects some pathological case related
            // to nested classes exists.
            Type rawType = parameterizedType.getRawType();
            checkArgument(rawType instanceof Class,
                    "Expected a Class, but <%s> is of type %s", type, type.getClass().getName());
            //noinspection ConstantConditions
            return (Class<?>) rawType;

        } else if (type instanceof GenericArrayType) {
            Type componentType = ((GenericArrayType) type).getGenericComponentType();
            return Array.newInstance(getRawType(componentType), 0).getClass();

        } else if (type instanceof TypeVariable) {
            // we could use the variable's bounds, but that'll won't work if there are multiple.
            // having a raw type that's more general than necessary is okay
            return Object.class;

        } else {
            throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
                    + "GenericArrayType, but <" + type + "> is of type " + type.getClass().getName());
        }
    }
1169785
public List<MethodParameter> getParametersOfType(Class<?> type) {

		Assert.notNull(type, "Type must not be null!");

		return getParameters().stream() //
				.filter(it -> it.getParameterType().equals(type)) //
				.collect(Collectors.toList());
	}
253300
public Binder cast(Class<?> returnType, Class<?>... argTypes) {
        return new Binder(this, new Cast(type()), MethodType.methodType(returnType, argTypes));
    }
714408
public Method getMethod(Class<?> returnType, String name, Class<?>... paramTypes) {
        final Map<ParamList, Map<Class<?>, Method>> nameMap = methods.get(name);
        if (nameMap == null) {
            return null;
        }
        final Map<Class<?>, Method> paramsMap = nameMap.get(createParamList(paramTypes));
        if (paramsMap == null) {
            return null;
        }
        return paramsMap.get(returnType);
    }
340769
private static Class<?>[] getParamTypes(Context context, Object... arguments)
    {
        final Collection<Object> params = new ArrayList<>();
        params.add(context);
        params.addAll(Arrays.asList(arguments));
        return UtilReflection.getParamTypes(params.toArray());
    }
234056
private Type getAppropriateType(Class<?> type, Type genericType)
    {    
        return type.equals(genericType) ? type : genericType;
    }
967224
public static Method findMethod(Class<?> type, String name,
			Class<?>... parameterTypes) {
		while (type != null) {
			try {
				return type.getDeclaredMethod(name, parameterTypes);
			} catch (Exception e) {
			}
			type = type.getSuperclass();
		}
		return null;
	}
647043
public RuntimeTypeAdapterFactory<T> registerSubtype(Class<? extends T> type) {
    return registerSubtype(type, type.getSimpleName());
  }