Class TypeToken<T>

java.lang.Object
com.google.common.reflect.TypeCapture<T>
com.google.common.reflect.TypeToken<T>
All Implemented Interfaces:
Serializable
Direct Known Subclasses:
TypeToken.SimpleTypeToken

public abstract class TypeToken<T> extends TypeCapture<T> implements Serializable
A Type with generics.

Operations that are otherwise only available in Class are implemented to support Type, for example isSubtypeOf(com.google.common.reflect.TypeToken<?>), isArray() and getComponentType(). It also provides additional utilities such as getTypes(), resolveType(java.lang.reflect.Type), etc.

There are three ways to get a TypeToken instance:

  • Wrap a Type obtained via reflection. For example: TypeToken.of(method.getGenericReturnType()).
  • Capture a generic type with a (usually anonymous) subclass. For example:
    
     new TypeToken<List<String>>() {}
     

    Note that it's critical that the actual type argument is carried by a subclass. The following code is wrong because it only captures the <T> type variable of the listType() method signature; while <String> is lost in erasure:

    
     class Util {
       static <T> TypeToken<List<T>> listType() {
         return new TypeToken<List<T>>() {};
       }
     }
    
     TypeToken<List<String>> stringListType = Util.<String>listType();
     
  • Capture a generic type with a (usually anonymous) subclass and resolve it against a context class that knows what the type parameters are. For example:
    
     abstract class IKnowMyType<T> {
       TypeToken<T> type = new TypeToken<T>(getClass()) {};
     }
     new IKnowMyType<String>() {}.type => String
     

TypeToken is serializable when no type variable is contained in the type.

Note to Guice users: TypeToken is similar to Guice's TypeLiteral class except that it is serializable and offers numerous additional utility methods.

Since:
12.0
See Also:
  • Field Details

    • runtimeType

      private final Type runtimeType
    • invariantTypeResolver

      @CheckForNull private transient TypeResolver invariantTypeResolver
      Resolver for resolving parameter and field types with runtimeType as context.
    • covariantTypeResolver

      @CheckForNull private transient TypeResolver covariantTypeResolver
      Resolver for resolving covariant types with runtimeType as context.
    • serialVersionUID

      private static final long serialVersionUID
      See Also:
  • Constructor Details

    • TypeToken

      protected TypeToken()
      Constructs a new type token of T.

      Clients create an empty anonymous subclass. Doing so embeds the type parameter in the anonymous class's type hierarchy so we can reconstitute it at runtime despite erasure.

      For example:

      
       TypeToken<List<String>> t = new TypeToken<List<String>>() {};
       
    • TypeToken

      protected TypeToken(Class<?> declaringClass)
      Constructs a new type token of T while resolving free type variables in the context of declaringClass.

      Clients create an empty anonymous subclass. Doing so embeds the type parameter in the anonymous class's type hierarchy so we can reconstitute it at runtime despite erasure.

      For example:

      
       abstract class IKnowMyType<T> {
         TypeToken<T> getMyType() {
           return new TypeToken<T>(getClass()) {};
         }
       }
      
       new IKnowMyType<String>() {}.getMyType() => String
       
    • TypeToken

      private TypeToken(Type type)
  • Method Details

    • of

      public static <T> TypeToken<T> of(Class<T> type)
      Returns an instance of type token that wraps type.
    • of

      public static TypeToken<?> of(Type type)
      Returns an instance of type token that wraps type.
    • getRawType

      public final Class<? super T> getRawType()
      Returns the raw type of T. Formally speaking, if T is returned by Method.getGenericReturnType(), the raw type is what's returned by Method.getReturnType() of the same method object. Specifically:
      • If T is a Class itself, T itself is returned.
      • If T is a ParameterizedType, the raw type of the parameterized type is returned.
      • If T is a GenericArrayType, the returned type is the corresponding array class. For example: List<Integer>[] => List[].
      • If T is a type variable or a wildcard type, the raw type of the first upper bound is returned. For example: <X extends Foo> => Foo.
    • getType

      public final Type getType()
      Returns the represented type.
    • where

      public final <X> TypeToken<T> where(TypeParameter<X> typeParam, TypeToken<X> typeArg)
      Returns a new TypeToken where type variables represented by typeParam are substituted by typeArg. For example, it can be used to construct Map<K, V> for any K and V type:
      
       static <K, V> TypeToken<Map<K, V>> mapOf(
           TypeToken<K> keyType, TypeToken<V> valueType) {
         return new TypeToken<Map<K, V>>() {}
             .where(new TypeParameter<K>() {}, keyType)
             .where(new TypeParameter<V>() {}, valueType);
       }
       
      Type Parameters:
      X - The parameter type
      Parameters:
      typeParam - the parameter type variable
      typeArg - the actual type to substitute
    • where

      public final <X> TypeToken<T> where(TypeParameter<X> typeParam, Class<X> typeArg)
      Returns a new TypeToken where type variables represented by typeParam are substituted by typeArg. For example, it can be used to construct Map<K, V> for any K and V type:
      
       static <K, V> TypeToken<Map<K, V>> mapOf(
           Class<K> keyType, Class<V> valueType) {
         return new TypeToken<Map<K, V>>() {}
             .where(new TypeParameter<K>() {}, keyType)
             .where(new TypeParameter<V>() {}, valueType);
       }
       
      Type Parameters:
      X - The parameter type
      Parameters:
      typeParam - the parameter type variable
      typeArg - the actual type to substitute
    • resolveType

      public final TypeToken<?> resolveType(Type type)
      Resolves the given type against the type context represented by this type. For example:
      
       new TypeToken<List<String>>() {}.resolveType(
           List.class.getMethod("get", int.class).getGenericReturnType())
       => String.class
       
    • resolveSupertype

      private TypeToken<?> resolveSupertype(Type type)
    • getGenericSuperclass

      @CheckForNull final TypeToken<? super T> getGenericSuperclass()
      Returns the generic superclass of this type or null if the type represents Object or an interface. This method is similar but different from Class.getGenericSuperclass(). For example, new TypeToken<StringArrayList>() {}.getGenericSuperclass() will return new TypeToken<ArrayList<String>>() {}; while StringArrayList.class.getGenericSuperclass() will return ArrayList<E>, where E is the type variable declared by class ArrayList.

      If this type is a type variable or wildcard, its first upper bound is examined and returned if the bound is a class or extends from a class. This means that the returned type could be a type variable too.

    • boundAsSuperclass

      @CheckForNull private TypeToken<? super T> boundAsSuperclass(Type bound)
    • getGenericInterfaces

      final ImmutableList<TypeToken<? super T>> getGenericInterfaces()
      Returns the generic interfaces that this type directly implements. This method is similar but different from Class.getGenericInterfaces(). For example, new TypeToken<List<String>>() {}.getGenericInterfaces() will return a list that contains new TypeToken<Iterable<String>>() {}; while List.class.getGenericInterfaces() will return an array that contains Iterable<T>, where the T is the type variable declared by interface Iterable.

      If this type is a type variable or wildcard, its upper bounds are examined and those that are either an interface or upper-bounded only by interfaces are returned. This means that the returned types could include type variables too.

    • boundsAsInterfaces

      private ImmutableList<TypeToken<? super T>> boundsAsInterfaces(Type[] bounds)
    • getTypes

      public final TypeToken<T>.TypeSet getTypes()
      Returns the set of interfaces and classes that this type is or is a subtype of. The returned types are parameterized with proper type arguments.

      Subtypes are always listed before supertypes. But the reverse is not true. A type isn't necessarily a subtype of all the types following. Order between types without subtype relationship is arbitrary and not guaranteed.

      If this type is a type variable or wildcard, upper bounds that are themselves type variables aren't included (their super interfaces and superclasses are).

    • getSupertype

      public final TypeToken<? super T> getSupertype(Class<? super T> superclass)
      Returns the generic form of superclass. For example, if this is ArrayList<String>, Iterable<String> is returned given the input Iterable.class.
    • getSubtype

      public final TypeToken<? extends T> getSubtype(Class<?> subclass)
      Returns subtype of this with subclass as the raw class. For example, if this is Iterable<String> and subclass is List, List<String> is returned.
    • isSupertypeOf

      public final boolean isSupertypeOf(TypeToken<?> type)
      Returns true if this type is a supertype of the given type. "Supertype" is defined according to the rules for type arguments introduced with Java generics.
      Since:
      19.0
    • isSupertypeOf

      public final boolean isSupertypeOf(Type type)
      Returns true if this type is a supertype of the given type. "Supertype" is defined according to the rules for type arguments introduced with Java generics.
      Since:
      19.0
    • isSubtypeOf

      public final boolean isSubtypeOf(TypeToken<?> type)
      Returns true if this type is a subtype of the given type. "Subtype" is defined according to the rules for type arguments introduced with Java generics.
      Since:
      19.0
    • isSubtypeOf

      public final boolean isSubtypeOf(Type supertype)
      Returns true if this type is a subtype of the given type. "Subtype" is defined according to the rules for type arguments introduced with Java generics.
      Since:
      19.0
    • isArray

      public final boolean isArray()
      Returns true if this type is known to be an array type, such as int[], T[], <? extends Map<String, Integer>[]> etc.
    • isPrimitive

      public final boolean isPrimitive()
      Returns true if this type is one of the nine primitive types (including void).
      Since:
      15.0
    • wrap

      public final TypeToken<T> wrap()
      Returns the corresponding wrapper type if this is a primitive type; otherwise returns this itself. Idempotent.
      Since:
      15.0
    • isWrapper

      private boolean isWrapper()
    • unwrap

      public final TypeToken<T> unwrap()
      Returns the corresponding primitive type if this is a wrapper type; otherwise returns this itself. Idempotent.
      Since:
      15.0
    • getComponentType

      @CheckForNull public final TypeToken<?> getComponentType()
      Returns the array component type if this type represents an array (int[], T[], <? extends Map<String, Integer>[]> etc.), or else null is returned.
    • method

      public final Invokable<T,Object> method(Method method)
      Returns the Invokable for method, which must be a member of T.
      Since:
      14.0
    • constructor

      public final Invokable<T,T> constructor(Constructor<?> constructor)
      Returns the Invokable for constructor, which must be a member of T.
      Since:
      14.0
    • equals

      public boolean equals(@CheckForNull Object o)
      Returns true if o is another TypeToken that represents the same Type.
      Overrides:
      equals in class Object
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class Object
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • writeReplace

      protected Object writeReplace()
      Implemented to support serialization of subclasses.
    • rejectTypeVariables

      final TypeToken<T> rejectTypeVariables()
      Ensures that this type token doesn't contain type variables, which can cause unchecked type errors for callers like TypeToInstanceMap.
    • someRawTypeIsSubclassOf

      private boolean someRawTypeIsSubclassOf(Class<?> superclass)
    • isSubtypeOfParameterizedType

      private boolean isSubtypeOfParameterizedType(ParameterizedType supertype)
    • isSubtypeOfArrayType

      private boolean isSubtypeOfArrayType(GenericArrayType supertype)
    • isSupertypeOfArray

      private boolean isSupertypeOfArray(GenericArrayType subtype)
    • is

      private boolean is(Type formalType, TypeVariable<?> declaration)
      A.is(B) is defined as Foo<A>.isSubtypeOf(Foo<B>).

      Specifically, returns true if any of the following conditions is met:

      1. 'this' and formalType are equal.
      2. 'this' and formalType have equal canonical form.
      3. formalType is <? extends Foo> and 'this' is a subtype of Foo.
      4. formalType is <? super Foo> and 'this' is a supertype of Foo.
      Note that condition 2 isn't technically accurate under the context of a recursively bounded type variables. For example, Enum<? extends Enum<E>> canonicalizes to Enum<?> where E is the type variable declared on the Enum class declaration. It's technically not true that Foo<Enum<? extends Enum<E>>> is a subtype of Foo<Enum<?>> according to JLS. See testRecursiveWildcardSubtypeBug() for a real example.

      It appears that properly handling recursive type bounds in the presence of implicit type bounds is not easy. For now we punt, hoping that this defect should rarely cause issues in real code.

      Parameters:
      formalType - is Foo<formalType> a supertype of Foo<T>?
      declaration - The type variable in the context of a parameterized type. Used to infer type bound when formalType is a wildcard with implicit upper bound.
    • canonicalizeTypeArg

      private static Type canonicalizeTypeArg(TypeVariable<?> declaration, Type typeArg)
      In reflection, Foo<?>.getUpperBounds()[0] is always Object.class, even when Foo is defined as Foo<T extends String>. Thus directly calling <?>.is(String.class) will return false. To mitigate, we canonicalize wildcards by enforcing the following invariants:
      1. canonicalize(t) always produces the equal result for equivalent types. For example both Enum<?> and Enum<? extends Enum<?>> canonicalize to Enum<? extends Enum<E>.
      2. canonicalize(t) produces a "literal" supertype of t. For example: Enum<? extends Enum<?>> canonicalizes to Enum<?>, which is a supertype (if we disregard the upper bound is implicitly an Enum too).
      3. If canonicalize(A) == canonicalize(B), then Foo<A>.isSubtypeOf(Foo<B>) and vice versa. i.e. A.is(B) and B.is(A).
      4. canonicalize(canonicalize(A)) == canonicalize(A).
    • canonicalizeWildcardsInType

      private static Type canonicalizeWildcardsInType(Type type)
    • canonicalizeWildcardType

      private static WildcardType canonicalizeWildcardType(TypeVariable<?> declaration, WildcardType type)
    • canonicalizeWildcardsInParameterizedType

      private static ParameterizedType canonicalizeWildcardsInParameterizedType(ParameterizedType type)
    • every

      private static TypeToken.Bounds every(Type[] bounds)
    • any

      private static TypeToken.Bounds any(Type[] bounds)
    • getRawTypes

      private ImmutableSet<Class<? super T>> getRawTypes()
    • isOwnedBySubtypeOf

      private boolean isOwnedBySubtypeOf(Type supertype)
    • getOwnerTypeIfPresent

      @CheckForNull private Type getOwnerTypeIfPresent()
      Returns the owner type of a ParameterizedType or enclosing class of a Class, or null otherwise.
    • toGenericType

      static <T> TypeToken<? extends T> toGenericType(Class<T> cls)
      Returns the type token representing the generic type declaration of cls. For example: TypeToken.getGenericType(Iterable.class) returns Iterable<T>.

      If cls isn't parameterized and isn't a generic array, the type token of the class is returned.

    • getCovariantTypeResolver

      private TypeResolver getCovariantTypeResolver()
    • getInvariantTypeResolver

      private TypeResolver getInvariantTypeResolver()
    • getSupertypeFromUpperBounds

      private TypeToken<? super T> getSupertypeFromUpperBounds(Class<? super T> supertype, Type[] upperBounds)
    • getSubtypeFromLowerBounds

      private TypeToken<? extends T> getSubtypeFromLowerBounds(Class<?> subclass, Type[] lowerBounds)
    • getArraySupertype

      private TypeToken<? super T> getArraySupertype(Class<? super T> supertype)
    • getArraySubtype

      private TypeToken<? extends T> getArraySubtype(Class<?> subclass)
    • resolveTypeArgsForSubclass

      private Type resolveTypeArgsForSubclass(Class<?> subclass)
    • newArrayClassOrGenericArrayType

      private static Type newArrayClassOrGenericArrayType(Type componentType)
      Creates an array class if componentType is a class, or else, a GenericArrayType. This is what Java7 does for generic array type parameters.