Class TypeResolver

java.lang.Object
net.jodah.typetools.TypeResolver

public final class TypeResolver extends Object
Enhanced type resolution utilities.
  • Field Details

    • TYPE_VARIABLE_CACHE

      private static final Map<Class<?>,Reference<Map<TypeVariable<?>,Type>>> TYPE_VARIABLE_CACHE
      Cache of type variable/argument pairs
    • CACHE_ENABLED

      private static volatile boolean CACHE_ENABLED
    • RESOLVES_LAMBDAS

      private static boolean RESOLVES_LAMBDAS
    • JAVA_LANG_ACCESS

      private static Object JAVA_LANG_ACCESS
    • GET_CONSTANT_POOL

      private static Method GET_CONSTANT_POOL
    • GET_CONSTANT_POOL_SIZE

      private static Method GET_CONSTANT_POOL_SIZE
    • GET_CONSTANT_POOL_METHOD_AT

      private static Method GET_CONSTANT_POOL_METHOD_AT
    • OBJECT_METHODS

      private static final Map<String,Method> OBJECT_METHODS
    • PRIMITIVE_WRAPPERS

      private static final Map<Class<?>,Class<?>> PRIMITIVE_WRAPPERS
    • JAVA_VERSION

      private static final Double JAVA_VERSION
  • Constructor Details

    • TypeResolver

      private TypeResolver()
  • Method Details

    • enableCache

      public static void enableCache()
      Enables the internal caching of resolved TypeVariables.
    • disableCache

      public static void disableCache()
      Disables the internal caching of resolved TypeVariables.
    • resolveRawArgument

      public static <T, S extends T> Class<?> resolveRawArgument(Class<T> type, Class<S> subType)
      Returns the raw class representing the argument for the type using type variable information from the subType. If no arguments can be resolved then Unknown.class is returned.
      Parameters:
      type - to resolve argument for
      subType - to extract type variable information from
      Returns:
      argument for type else TypeResolver.Unknown.class if no type arguments are declared
      Throws:
      IllegalArgumentException - if more or less than one argument is resolved for the type
    • resolveRawArgument

      public static Class<?> resolveRawArgument(Type genericType, Class<?> subType)
      Returns the raw class representing the argument for the genericType using type variable information from the subType. If genericType is an instance of class, then genericType is returned. If no arguments can be resolved then Unknown.class is returned.
      Parameters:
      genericType - to resolve argument for
      subType - to extract type variable information from
      Returns:
      argument for genericType else TypeResolver.Unknown.class if no type arguments are declared
      Throws:
      IllegalArgumentException - if more or less than one argument is resolved for the genericType
    • resolveRawArguments

      public static <T, S extends T> Class<?>[] resolveRawArguments(Class<T> type, Class<S> subType)
      Returns an array of raw classes representing arguments for the type using type variable information from the subType. Arguments for type that cannot be resolved are returned as Unknown.class. If no arguments can be resolved then null is returned.
      Parameters:
      type - to resolve arguments for
      subType - to extract type variable information from
      Returns:
      array of raw classes representing arguments for the type else null if no type arguments are declared
    • reify

      public static <T, S extends T> Type reify(Class<T> type, Class<S> context)
      Traverses a generic type and replaces all type variables and wildcard types with concrete types (if possible), by using the type information from given context. A convenience method which largely works the same as reify(Type, Class), but first resolves the generic type of type.
      Parameters:
      type - the class whose generic type to traverse
      context - the class that serves as starting point to resolve replacements of type variables
      Returns:
      a type that is structurally the same as type, except that type variables and wildcard types have been replaced with concrete types
      Throws:
      UnsupportedOperationException - if type (or a type that it references) is not an instance of one of the following types: Class, TypeVariable, WildcardType, ParameterizedType, GenericArrayType.
      UnsupportedOperationException - if type (or a type that it references) is a WildcardType that does not have exactly one upper bound, or does not have no lower bounds.
      UnsupportedOperationException - if type (or a type that it references) is a GenericArrayType whose generic component type cannot be reified to an instance of Class.
    • reify

      public static Type reify(Type type, Class<?> context)
      Traverses a generic type and replaces all type variables and wildcard types with concrete types (if possible), by using the type information from given context. Generic types used as input to this method are commonly obtained using reflection, e.g. via Field.getGenericType(), Method.getGenericReturnType(), Method.getGenericParameterTypes(). Example:
      
         class A<T> {
           public T something;
           public Optional<List<T>> compute() { ... }
         }
      
         class B extends A<Number> {
           public <? extends Collection<List<?>>> collect() { ... }
         }
       
      Reifying the generic return type of the method compute with B.class as context will yield the parameterized type Optional<List<Number>>. Note that not the raw type (Optional is returned, but the input type is reified recursively. Reifying the generic type of the field something with B.class as context will yield Number.class. Note that type variables with no explicit upper bound are reified to Object, and Unknown.class is never returned.
      Parameters:
      type - the generic type to traverse
      context - the class that serves as starting point to resolve replacements of type variables
      Returns:
      a type that is structurally the same as type, except that type variables and wildcard types have been replaced with concrete types
      Throws:
      UnsupportedOperationException - if type (or a type that it references) is not an instance of one of the following types: Class, TypeVariable, WildcardType, ParameterizedType, GenericArrayType.
      UnsupportedOperationException - if type (or a type that it references) is a WildcardType that does not have exactly one upper bound, or does not have no lower bounds.
      UnsupportedOperationException - if type (or a type that it references) is a GenericArrayType whose generic component type cannot be reified to an instance of Class.
    • reify

      public static Type reify(Type type)
      Traverses a generic type and replaces all type variables and wildcard types with concrete types (if possible). A convenience wrapper around reify(Type, Class), for when no context is needed/available. Generic types used as input to this method are commonly obtained using reflection, e.g. via Field.getGenericType(), Method.getGenericReturnType(), Method.getGenericParameterTypes(). Example:
      
         class X {
           public List<? extends Collection<List<? extends Number>>> collectList() { ... }
           public Set<?> collectSet() { ... }
         }
       
      Reifying the generic return type of the method collectList will yield the parameterized type List<Collection<List<Number>>>. Reifying the generic return type of the method collectSet will yield the parameterized type Set<Object>, since there is no explicit upper bound for the wildcard type given.
      Parameters:
      type - the generic type to traverse
      Returns:
      a type that is structurally the same as type, except that type variables and wildcard types have been replaced with concrete types
      Throws:
      UnsupportedOperationException - if type (or a type that it references) is not an instance of one of the following types: Class, TypeVariable, WildcardType, ParameterizedType, GenericArrayType.
      UnsupportedOperationException - if type (or a type that it references) is a WildcardType that does not have exactly one upper bound, or does not have no lower bounds.
      UnsupportedOperationException - if type (or a type that it references) is a GenericArrayType whose generic component type cannot be reified to an instance of Class.
    • resolveRawArguments

      public static Class<?>[] resolveRawArguments(Type genericType, Class<?> subType)
      Returns an array of raw classes representing arguments for the genericType using type variable information from the subType. Arguments for genericType that cannot be resolved are returned as Unknown.class. If no arguments can be resolved then null is returned.
      Parameters:
      genericType - to resolve arguments for
      subType - to extract type variable information from
      Returns:
      array of raw classes representing arguments for the genericType else null if no type arguments are declared
    • resolveGenericType

      public static Type resolveGenericType(Class<?> type, Type subType)
      Returns the generic type using type variable information from the subType else null if the generic type cannot be resolved.
      Parameters:
      type - to resolve generic type for
      subType - to extract type variable information from
      Returns:
      generic type else null if it cannot be resolved
    • resolveRawClass

      public static Class<?> resolveRawClass(Type genericType, Class<?> subType)
      Resolves the raw class for the genericType, using the type variable information from the subType else TypeResolver.Unknown if the raw class cannot be resolved.
      Parameters:
      genericType - to resolve raw class for
      subType - to extract type variable information from
      Returns:
      raw class for the genericType else TypeResolver.Unknown if it cannot be resolved
    • resolveRawClass

      private static Class<?> resolveRawClass(Type genericType, Class<?> subType, Class<?> functionalInterface)
    • reify

      private static Type reify(Type genericType, Map<TypeVariable<?>,Type> typeVariableTypeMap)
    • reify

      private static Type reify(Type genericType, Map<TypeVariable<?>,Type> typeVariableMap, Map<ParameterizedType,ReifiedParameterizedType> partial)
      Works like resolveRawClass(Type, Class, Class) but does not stop at raw classes. Instead, traverses referenced types.
      Parameters:
      partial - contains a mapping of generic types to reified types. A value of null inside a ReifiedParameterizedType instance means that this type is currently being reified.
    • getTypeVariableMap

      private static Map<TypeVariable<?>,Type> getTypeVariableMap(Class<?> targetType, Class<?> functionalInterface)
    • populateSuperTypeArgs

      private static void populateSuperTypeArgs(Type[] types, Map<TypeVariable<?>,Type> map, boolean depthFirst)
      Populates the map with with variable/argument pairs for the given types.
    • populateTypeArgs

      private static void populateTypeArgs(ParameterizedType type, Map<TypeVariable<?>,Type> map, boolean depthFirst)
      Populates the map with variable/argument pairs for the given type.
    • resolveBound

      public static Type resolveBound(TypeVariable<?> typeVariable)
      Resolves the first bound for the typeVariable, returning Unknown.class if none can be resolved.
    • populateLambdaArgs

      private static void populateLambdaArgs(Class<?> functionalInterface, Class<?> lambdaType, Map<TypeVariable<?>,Type> map)
      Populates the map with variable/argument pairs for the functionalInterface.
    • isDefaultMethod

      private static boolean isDefaultMethod(Method m)
    • getMemberRef

      private static Member getMemberRef(Class<?> type)
    • isAutoBoxingMethod

      private static boolean isAutoBoxingMethod(Method method)
    • wrapPrimitives

      private static Class<?> wrapPrimitives(Class<?> clazz)
    • getConstantPoolSize

      private static int getConstantPoolSize(Object constantPool)
    • getConstantPoolMethodAt

      private static Member getConstantPoolMethodAt(Object constantPool, int i)