Class TypeResolver

  • All Implemented Interfaces:
    java.io.Serializable

    public class TypeResolver
    extends java.lang.Object
    implements java.io.Serializable
    Object that is used for resolving generic type information of a class so that it is accessible using simple API. Resolved types are also starting point for accessing resolved (generics aware) return and argument types of class members (methods, fields, constructors).

    Note that resolver instances are stateful in that resolvers cache resolved types for efficiency. Since this is internal state and not directly visible to callers, access to state is fully synchronized so that access from multiple threads is safe.

    See Also:
    Serialized Form
    • Field Detail

      • sJavaLangObject

        private static final ResolvedObjectType sJavaLangObject
        We will also need to return "unknown" type for cases where type variable binding is not found ('raw' instances of generic types); easiest way is to pre-create type for java.lang.Object
      • _primitiveTypes

        protected static final java.util.HashMap<ClassKey,​ResolvedType> _primitiveTypes
        Since number of primitive types is small, and they are frequently needed, let's actually pre-create them for efficient reuse. Same goes for limited number of other "standard" types...
      • _resolvedTypes

        protected final ResolvedTypeCache _resolvedTypes
        Simple cache of types resolved by this resolver. Caching works because type instances themselves are mostly immutable; and properly synchronized in cases where transient data (raw members) are accessed.
    • Constructor Detail

      • TypeResolver

        public TypeResolver()
        Constructs type cache; equivalent to:
         
           TypeResolver(ResolvedTypeCache.lruCache(200));
        
      • TypeResolver

        public TypeResolver​(ResolvedTypeCache typeCache)
        Constructor that specifies type cache to use.
        Parameters:
        typeCache - Cache to use for avoiding repeated resolution of already resolved types
        Since:
        1.4
    • Method Detail

      • resolve

        public ResolvedType resolve​(java.lang.reflect.Type type,
                                    java.lang.reflect.Type... typeParameters)
        Factory method for resolving given base type using specified types as type parameters. Sample usage would be:
          ResolvedType type = TypeResolver.resolve(List.class, Integer.class);
        
        which would be equivalent to
          ResolvedType type = TypeResolver.resolve(new GenericType<List<Integer>>() { });
        
        Note that you can mix different types of type parameters, whether already resolved (ResolvedType), type-erased (Class) or generic type reference (GenericType).
      • arrayType

        public ResolvedArrayType arrayType​(java.lang.reflect.Type elementType)
        Factory method for constructing array type of given element type.
      • resolve

        public ResolvedType resolve​(TypeBindings typeBindings,
                                    java.lang.reflect.Type jdkType)
        Factory method for resolving specified Java Type, given TypeBindings needed to resolve any type variables.

        Use of this method is discouraged (use if and only if you really know what you are doing!); but if used, type bindings passed should come from ResolvedType instance of declaring class (or interface).

        NOTE: order of arguments was reversed for 0.8, to avoid problems with overload varargs method.

      • resolveSubtype

        public ResolvedType resolveSubtype​(ResolvedType supertype,
                                           java.lang.Class<?> subtype)
                                    throws java.lang.IllegalArgumentException,
                                           java.lang.UnsupportedOperationException
        Factory method for constructing sub-classing specified type; class specified as sub-class must be compatible according to basic Java inheritance rules (subtype must properly extend or implement specified supertype).

        A typical use case here is to refine a generic type; for example, given that we have generic type like List<Integer>, but we want a more specific implementation type like class ArrayList but with same parameterization (here just Integer), we could achieve it by:

          ResolvedType mapType = typeResolver.resolve(List.class, Integer.class);
          ResolveType concreteMapType = typeResolver.resolveSubType(mapType, ArrayList.class);
        
        (in this case, it would have been simpler to resolve directly; but in some cases we are handled supertype and want to refine it, in which case steps would be the same but separated by other code)

        Note that this method will fail if extension can not succeed; either because this type is not extendable (sub-classable) -- which is true for primitive and array types -- or because given class is not a subtype of this type. To check whether subtyping could succeed, you can call ResolvedType.canCreateSubtypes() to see if supertype can ever be extended.

        Parameters:
        supertype - Type to subtype (extend)
        subtype - Type-erased sub-class or sub-interface
        Returns:
        Resolved subtype
        Throws:
        java.lang.IllegalArgumentException - If this type can be extended in general, but not into specified sub-class
        java.lang.UnsupportedOperationException - If this type can not be sub-classed
      • isSelfReference

        public static boolean isSelfReference​(ResolvedType type)
        Convenience method that can be used to checked whether given resolved type (with erased type of java.lang.Object) is a placeholder for "self-reference"; these are nasty recursive ("self") types needed with some interfaces
        Parameters:
        type - Type to check
      • _resolveTypePlaceholders

        private void _resolveTypePlaceholders​(ResolvedType sourceType,
                                              ResolvedType actualType)
                                       throws java.lang.IllegalArgumentException
        Method called to verify that types match; and if there are any placeholders, replace them in actualType.
        Parameters:
        sourceType - Original base type used for specification/refinement
        actualType - Base type instance after re-resolving, possibly containing type placeholders
        Throws:
        java.lang.IllegalArgumentException