Class TypeResolver


  • public final class TypeResolver
    extends java.lang.Object
    Enhanced type resolution utilities.
    • Constructor Summary

      Constructors 
      Modifier Constructor Description
      private TypeResolver()  
    • Method Summary

      All Methods Static Methods Concrete Methods 
      Modifier and Type Method Description
      static void disableCache()
      Disables the internal caching of resolved TypeVariables.
      static void enableCache()
      Enables the internal caching of resolved TypeVariables.
      private static java.lang.reflect.Member getConstantPoolMethodAt​(java.lang.Object constantPool, int i)  
      private static int getConstantPoolSize​(java.lang.Object constantPool)  
      private static java.lang.reflect.Member getMemberRef​(java.lang.Class<?> type)  
      private static java.util.Map<java.lang.reflect.TypeVariable<?>,​java.lang.reflect.Type> getTypeVariableMap​(java.lang.Class<?> targetType, java.lang.Class<?> functionalInterface)  
      private static boolean isAutoBoxingMethod​(java.lang.reflect.Method method)  
      private static boolean isDefaultMethod​(java.lang.reflect.Method m)  
      private static void populateLambdaArgs​(java.lang.Class<?> functionalInterface, java.lang.Class<?> lambdaType, java.util.Map<java.lang.reflect.TypeVariable<?>,​java.lang.reflect.Type> map)
      Populates the map with variable/argument pairs for the functionalInterface.
      private static void populateSuperTypeArgs​(java.lang.reflect.Type[] types, java.util.Map<java.lang.reflect.TypeVariable<?>,​java.lang.reflect.Type> map, boolean depthFirst)
      Populates the map with with variable/argument pairs for the given types.
      private static void populateTypeArgs​(java.lang.reflect.ParameterizedType type, java.util.Map<java.lang.reflect.TypeVariable<?>,​java.lang.reflect.Type> map, boolean depthFirst)
      Populates the map with variable/argument pairs for the given type.
      static <T,​S extends T>
      java.lang.reflect.Type
      reify​(java.lang.Class<T> type, java.lang.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.
      static java.lang.reflect.Type reify​(java.lang.reflect.Type type)
      Traverses a generic type and replaces all type variables and wildcard types with concrete types (if possible).
      static java.lang.reflect.Type reify​(java.lang.reflect.Type type, java.lang.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.
      private static java.lang.reflect.Type reify​(java.lang.reflect.Type genericType, java.util.Map<java.lang.reflect.TypeVariable<?>,​java.lang.reflect.Type> typeVariableTypeMap)  
      private static java.lang.reflect.Type reify​(java.lang.reflect.Type genericType, java.util.Map<java.lang.reflect.TypeVariable<?>,​java.lang.reflect.Type> typeVariableMap, java.util.Map<java.lang.reflect.ParameterizedType,​ReifiedParameterizedType> partial)
      Works like resolveRawClass(Type, Class, Class) but does not stop at raw classes.
      static java.lang.reflect.Type resolveBound​(java.lang.reflect.TypeVariable<?> typeVariable)
      Resolves the first bound for the typeVariable, returning Unknown.class if none can be resolved.
      static java.lang.reflect.Type resolveGenericType​(java.lang.Class<?> type, java.lang.reflect.Type subType)
      Returns the generic type using type variable information from the subType else null if the generic type cannot be resolved.
      static <T,​S extends T>
      java.lang.Class<?>
      resolveRawArgument​(java.lang.Class<T> type, java.lang.Class<S> subType)
      Returns the raw class representing the argument for the type using type variable information from the subType.
      static java.lang.Class<?> resolveRawArgument​(java.lang.reflect.Type genericType, java.lang.Class<?> subType)
      Returns the raw class representing the argument for the genericType using type variable information from the subType.
      static <T,​S extends T>
      java.lang.Class<?>[]
      resolveRawArguments​(java.lang.Class<T> type, java.lang.Class<S> subType)
      Returns an array of raw classes representing arguments for the type using type variable information from the subType.
      static java.lang.Class<?>[] resolveRawArguments​(java.lang.reflect.Type genericType, java.lang.Class<?> subType)
      Returns an array of raw classes representing arguments for the genericType using type variable information from the subType.
      static java.lang.Class<?> resolveRawClass​(java.lang.reflect.Type genericType, java.lang.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.
      private static java.lang.Class<?> resolveRawClass​(java.lang.reflect.Type genericType, java.lang.Class<?> subType, java.lang.Class<?> functionalInterface)  
      private static java.lang.Class<?> wrapPrimitives​(java.lang.Class<?> clazz)  
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Field Detail

      • TYPE_VARIABLE_CACHE

        private static final java.util.Map<java.lang.Class<?>,​java.lang.ref.Reference<java.util.Map<java.lang.reflect.TypeVariable<?>,​java.lang.reflect.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 java.lang.Object JAVA_LANG_ACCESS
      • GET_CONSTANT_POOL

        private static java.lang.reflect.Method GET_CONSTANT_POOL
      • GET_CONSTANT_POOL_SIZE

        private static java.lang.reflect.Method GET_CONSTANT_POOL_SIZE
      • GET_CONSTANT_POOL_METHOD_AT

        private static java.lang.reflect.Method GET_CONSTANT_POOL_METHOD_AT
      • OBJECT_METHODS

        private static final java.util.Map<java.lang.String,​java.lang.reflect.Method> OBJECT_METHODS
      • PRIMITIVE_WRAPPERS

        private static final java.util.Map<java.lang.Class<?>,​java.lang.Class<?>> PRIMITIVE_WRAPPERS
      • JAVA_VERSION

        private static final java.lang.Double JAVA_VERSION
    • Constructor Detail

      • TypeResolver

        private TypeResolver()
    • Method Detail

      • 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> java.lang.Class<?> resolveRawArgument​(java.lang.Class<T> type,
                                                                                  java.lang.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:
        java.lang.IllegalArgumentException - if more or less than one argument is resolved for the type
      • resolveRawArgument

        public static java.lang.Class<?> resolveRawArgument​(java.lang.reflect.Type genericType,
                                                            java.lang.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:
        java.lang.IllegalArgumentException - if more or less than one argument is resolved for the genericType
      • resolveRawArguments

        public static <T,​S extends T> java.lang.Class<?>[] resolveRawArguments​(java.lang.Class<T> type,
                                                                                     java.lang.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> java.lang.reflect.Type reify​(java.lang.Class<T> type,
                                                                         java.lang.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:
        java.lang.UnsupportedOperationException - if type (or a type that it references) is not an instance of one of the following types: Class, TypeVariable, WildcardType, ParameterizedType, GenericArrayType.
        java.lang.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.
        java.lang.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 java.lang.reflect.Type reify​(java.lang.reflect.Type type,
                                                   java.lang.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:
        java.lang.UnsupportedOperationException - if type (or a type that it references) is not an instance of one of the following types: Class, TypeVariable, WildcardType, ParameterizedType, GenericArrayType.
        java.lang.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.
        java.lang.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 java.lang.reflect.Type reify​(java.lang.reflect.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:
        java.lang.UnsupportedOperationException - if type (or a type that it references) is not an instance of one of the following types: Class, TypeVariable, WildcardType, ParameterizedType, GenericArrayType.
        java.lang.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.
        java.lang.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 java.lang.Class<?>[] resolveRawArguments​(java.lang.reflect.Type genericType,
                                                               java.lang.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 java.lang.reflect.Type resolveGenericType​(java.lang.Class<?> type,
                                                                java.lang.reflect.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 java.lang.Class<?> resolveRawClass​(java.lang.reflect.Type genericType,
                                                         java.lang.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 java.lang.Class<?> resolveRawClass​(java.lang.reflect.Type genericType,
                                                          java.lang.Class<?> subType,
                                                          java.lang.Class<?> functionalInterface)
      • reify

        private static java.lang.reflect.Type reify​(java.lang.reflect.Type genericType,
                                                    java.util.Map<java.lang.reflect.TypeVariable<?>,​java.lang.reflect.Type> typeVariableTypeMap)
      • reify

        private static java.lang.reflect.Type reify​(java.lang.reflect.Type genericType,
                                                    java.util.Map<java.lang.reflect.TypeVariable<?>,​java.lang.reflect.Type> typeVariableMap,
                                                    java.util.Map<java.lang.reflect.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 java.util.Map<java.lang.reflect.TypeVariable<?>,​java.lang.reflect.Type> getTypeVariableMap​(java.lang.Class<?> targetType,
                                                                                                                        java.lang.Class<?> functionalInterface)
      • populateSuperTypeArgs

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

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

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

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

        private static boolean isDefaultMethod​(java.lang.reflect.Method m)
      • getMemberRef

        private static java.lang.reflect.Member getMemberRef​(java.lang.Class<?> type)
      • isAutoBoxingMethod

        private static boolean isAutoBoxingMethod​(java.lang.reflect.Method method)
      • wrapPrimitives

        private static java.lang.Class<?> wrapPrimitives​(java.lang.Class<?> clazz)
      • getConstantPoolSize

        private static int getConstantPoolSize​(java.lang.Object constantPool)
      • getConstantPoolMethodAt

        private static java.lang.reflect.Member getConstantPoolMethodAt​(java.lang.Object constantPool,
                                                                        int i)