Class TypeToken<T>
- java.lang.Object
-
- com.google.common.reflect.TypeCapture<T>
-
- com.google.common.reflect.TypeToken<T>
-
- All Implemented Interfaces:
java.io.Serializable
- Direct Known Subclasses:
TypeToken.SimpleTypeToken
@Beta public abstract class TypeToken<T> extends TypeCapture<T> implements java.io.Serializable
AType
with generics.Operations that are otherwise only available in
Class
are implemented to supportType
, for exampleisSubtypeOf(com.google.common.reflect.TypeToken<?>)
,isArray()
andgetComponentType()
. It also provides additional utilities such asgetTypes()
,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 thelistType()
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:
- Serialized Form
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private static class
TypeToken.Bounds
private class
TypeToken.ClassSet
private class
TypeToken.InterfaceSet
private static class
TypeToken.SimpleTypeToken<T>
private static class
TypeToken.TypeCollector<K>
Collects parent types from a sub type.private static class
TypeToken.TypeFilter
class
TypeToken.TypeSet
The set of interfaces and classes thatT
is or is a subtype of.
-
Field Summary
Fields Modifier and Type Field Description private TypeResolver
covariantTypeResolver
Resolver for resolving covariant types withruntimeType
as context.private TypeResolver
invariantTypeResolver
Resolver for resolving parameter and field types withruntimeType
as context.private java.lang.reflect.Type
runtimeType
private static long
serialVersionUID
-
Constructor Summary
Constructors Modifier Constructor Description protected
TypeToken()
Constructs a new type token ofT
.protected
TypeToken(java.lang.Class<?> declaringClass)
Constructs a new type token ofT
while resolving free type variables in the context ofdeclaringClass
.private
TypeToken(java.lang.reflect.Type type)
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description private static TypeToken.Bounds
any(java.lang.reflect.Type[] bounds)
private TypeToken<? super T>
boundAsSuperclass(java.lang.reflect.Type bound)
private ImmutableList<TypeToken<? super T>>
boundsAsInterfaces(java.lang.reflect.Type[] bounds)
private static java.lang.reflect.Type
canonicalizeTypeArg(java.lang.reflect.TypeVariable<?> declaration, java.lang.reflect.Type typeArg)
In reflection,Foo<?>.getUpperBounds()[0]
is alwaysObject.class
, even when Foo is defined asFoo<T extends String>
.private static java.lang.reflect.ParameterizedType
canonicalizeWildcardsInParameterizedType(java.lang.reflect.ParameterizedType type)
private static java.lang.reflect.Type
canonicalizeWildcardsInType(java.lang.reflect.Type type)
private static java.lang.reflect.WildcardType
canonicalizeWildcardType(java.lang.reflect.TypeVariable<?> declaration, java.lang.reflect.WildcardType type)
Invokable<T,T>
constructor(java.lang.reflect.Constructor<?> constructor)
boolean
equals(java.lang.Object o)
Returns true ifo
is anotherTypeToken
that represents the sameType
.private static TypeToken.Bounds
every(java.lang.reflect.Type[] bounds)
private TypeToken<? extends T>
getArraySubtype(java.lang.Class<?> subclass)
private TypeToken<? super T>
getArraySupertype(java.lang.Class<? super T> supertype)
TypeToken<?>
getComponentType()
Returns the array component type if this type represents an array (int[]
,T[]
,<? extends Map<String, Integer>[]>
etc.), or elsenull
is returned.private TypeResolver
getCovariantTypeResolver()
(package private) ImmutableList<TypeToken<? super T>>
getGenericInterfaces()
Returns the generic interfaces that this type directlyimplements
.(package private) TypeToken<? super T>
getGenericSuperclass()
Returns the generic superclass of this type ornull
if the type representsObject
or an interface.private TypeResolver
getInvariantTypeResolver()
private java.lang.reflect.Type
getOwnerTypeIfPresent()
Returns the owner type of aParameterizedType
or enclosing class of aClass
, or null otherwise.java.lang.Class<? super T>
getRawType()
Returns the raw type ofT
.private ImmutableSet<java.lang.Class<? super T>>
getRawTypes()
TypeToken<? extends T>
getSubtype(java.lang.Class<?> subclass)
Returns subtype ofthis
withsubclass
as the raw class.private TypeToken<? extends T>
getSubtypeFromLowerBounds(java.lang.Class<?> subclass, java.lang.reflect.Type[] lowerBounds)
TypeToken<? super T>
getSupertype(java.lang.Class<? super T> superclass)
Returns the generic form ofsuperclass
.private TypeToken<? super T>
getSupertypeFromUpperBounds(java.lang.Class<? super T> supertype, java.lang.reflect.Type[] upperBounds)
java.lang.reflect.Type
getType()
Returns the represented type.TypeToken.TypeSet
getTypes()
Returns the set of interfaces and classes that this type is or is a subtype of.int
hashCode()
private boolean
is(java.lang.reflect.Type formalType, java.lang.reflect.TypeVariable<?> declaration)
A.is(B)
is defined asFoo<A>.isSubtypeOf(Foo<B>)
.boolean
isArray()
Returns true if this type is known to be an array type, such asint[]
,T[]
,<? extends Map<String, Integer>[]>
etc.private boolean
isOwnedBySubtypeOf(java.lang.reflect.Type supertype)
boolean
isPrimitive()
Returns true if this type is one of the nine primitive types (includingvoid
).boolean
isSubtypeOf(TypeToken<?> type)
Returns true if this type is a subtype of the giventype
.boolean
isSubtypeOf(java.lang.reflect.Type supertype)
Returns true if this type is a subtype of the giventype
.private boolean
isSubtypeOfArrayType(java.lang.reflect.GenericArrayType supertype)
private boolean
isSubtypeOfParameterizedType(java.lang.reflect.ParameterizedType supertype)
boolean
isSupertypeOf(TypeToken<?> type)
Returns true if this type is a supertype of the giventype
.boolean
isSupertypeOf(java.lang.reflect.Type type)
Returns true if this type is a supertype of the giventype
.private boolean
isSupertypeOfArray(java.lang.reflect.GenericArrayType subtype)
private boolean
isWrapper()
Invokable<T,java.lang.Object>
method(java.lang.reflect.Method method)
private static java.lang.reflect.Type
newArrayClassOrGenericArrayType(java.lang.reflect.Type componentType)
Creates an array class ifcomponentType
is a class, or else, aGenericArrayType
.static <T> TypeToken<T>
of(java.lang.Class<T> type)
Returns an instance of type token that wrapstype
.static TypeToken<?>
of(java.lang.reflect.Type type)
Returns an instance of type token that wrapstype
.(package private) TypeToken<T>
rejectTypeVariables()
Ensures that this type token doesn't contain type variables, which can cause unchecked type errors for callers likeTypeToInstanceMap
.private TypeToken<?>
resolveSupertype(java.lang.reflect.Type type)
TypeToken<?>
resolveType(java.lang.reflect.Type type)
Resolves the giventype
against the type context represented by this type.private java.lang.reflect.Type
resolveTypeArgsForSubclass(java.lang.Class<?> subclass)
private boolean
someRawTypeIsSubclassOf(java.lang.Class<?> superclass)
(package private) static <T> TypeToken<? extends T>
toGenericType(java.lang.Class<T> cls)
Returns the type token representing the generic type declaration ofcls
.java.lang.String
toString()
TypeToken<T>
unwrap()
Returns the corresponding primitive type if this is a wrapper type; otherwise returnsthis
itself.<X> TypeToken<T>
where(TypeParameter<X> typeParam, TypeToken<X> typeArg)
Returns a newTypeToken
where type variables represented bytypeParam
are substituted bytypeArg
.<X> TypeToken<T>
where(TypeParameter<X> typeParam, java.lang.Class<X> typeArg)
Returns a newTypeToken
where type variables represented bytypeParam
are substituted bytypeArg
.TypeToken<T>
wrap()
Returns the corresponding wrapper type if this is a primitive type; otherwise returnsthis
itself.protected java.lang.Object
writeReplace()
Implemented to support serialization of subclasses.-
Methods inherited from class com.google.common.reflect.TypeCapture
capture
-
-
-
-
Field Detail
-
runtimeType
private final java.lang.reflect.Type runtimeType
-
invariantTypeResolver
private transient TypeResolver invariantTypeResolver
Resolver for resolving parameter and field types withruntimeType
as context.
-
covariantTypeResolver
private transient TypeResolver covariantTypeResolver
Resolver for resolving covariant types withruntimeType
as context.
-
serialVersionUID
private static final long serialVersionUID
- See Also:
- Constant Field Values
-
-
Constructor Detail
-
TypeToken
protected TypeToken()
Constructs a new type token ofT
.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(java.lang.Class<?> declaringClass)
Constructs a new type token ofT
while resolving free type variables in the context ofdeclaringClass
.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(java.lang.reflect.Type type)
-
-
Method Detail
-
of
public static <T> TypeToken<T> of(java.lang.Class<T> type)
Returns an instance of type token that wrapstype
.
-
of
public static TypeToken<?> of(java.lang.reflect.Type type)
Returns an instance of type token that wrapstype
.
-
getRawType
public final java.lang.Class<? super T> getRawType()
Returns the raw type ofT
. Formally speaking, ifT
is returned byMethod.getGenericReturnType()
, the raw type is what's returned byMethod.getReturnType()
of the same method object. Specifically:- If
T
is aClass
itself,T
itself is returned. - If
T
is aParameterizedType
, the raw type of the parameterized type is returned. - If
T
is aGenericArrayType
, 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
.
- If
-
getType
public final java.lang.reflect.Type getType()
Returns the represented type.
-
where
public final <X> TypeToken<T> where(TypeParameter<X> typeParam, TypeToken<X> typeArg)
Returns a newTypeToken
where type variables represented bytypeParam
are substituted bytypeArg
. For example, it can be used to constructMap<K, V>
for anyK
andV
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 variabletypeArg
- the actual type to substitute
-
where
public final <X> TypeToken<T> where(TypeParameter<X> typeParam, java.lang.Class<X> typeArg)
Returns a newTypeToken
where type variables represented bytypeParam
are substituted bytypeArg
. For example, it can be used to constructMap<K, V>
for anyK
andV
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 variabletypeArg
- the actual type to substitute
-
resolveType
public final TypeToken<?> resolveType(java.lang.reflect.Type type)
Resolves the giventype
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(java.lang.reflect.Type type)
-
getGenericSuperclass
final TypeToken<? super T> getGenericSuperclass()
Returns the generic superclass of this type ornull
if the type representsObject
or an interface. This method is similar but different fromClass.getGenericSuperclass()
. For example,new TypeToken<StringArrayList>() {}.getGenericSuperclass()
will returnnew TypeToken<ArrayList<String>>() {}
; whileStringArrayList.class.getGenericSuperclass()
will returnArrayList<E>
, whereE
is the type variable declared by classArrayList
.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.
-
getGenericInterfaces
final ImmutableList<TypeToken<? super T>> getGenericInterfaces()
Returns the generic interfaces that this type directlyimplements
. This method is similar but different fromClass.getGenericInterfaces()
. For example,new TypeToken<List<String>>() {}.getGenericInterfaces()
will return a list that containsnew TypeToken<Iterable<String>>() {}
; whileList.class.getGenericInterfaces()
will return an array that containsIterable<T>
, where theT
is the type variable declared by interfaceIterable
.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(java.lang.reflect.Type[] bounds)
-
getTypes
public final TypeToken.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(java.lang.Class<? super T> superclass)
Returns the generic form ofsuperclass
. For example, if this isArrayList<String>
,Iterable<String>
is returned given the inputIterable.class
.
-
getSubtype
public final TypeToken<? extends T> getSubtype(java.lang.Class<?> subclass)
Returns subtype ofthis
withsubclass
as the raw class. For example, if this isIterable<String>
andsubclass
isList
,List<String>
is returned.
-
isSupertypeOf
public final boolean isSupertypeOf(TypeToken<?> type)
Returns true if this type is a supertype of the giventype
. "Supertype" is defined according to the rules for type arguments introduced with Java generics.- Since:
- 19.0
-
isSupertypeOf
public final boolean isSupertypeOf(java.lang.reflect.Type type)
Returns true if this type is a supertype of the giventype
. "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 giventype
. "Subtype" is defined according to the rules for type arguments introduced with Java generics.- Since:
- 19.0
-
isSubtypeOf
public final boolean isSubtypeOf(java.lang.reflect.Type supertype)
Returns true if this type is a subtype of the giventype
. "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 asint[]
,T[]
,<? extends Map<String, Integer>[]>
etc.
-
isPrimitive
public final boolean isPrimitive()
Returns true if this type is one of the nine primitive types (includingvoid
).- Since:
- 15.0
-
wrap
public final TypeToken<T> wrap()
Returns the corresponding wrapper type if this is a primitive type; otherwise returnsthis
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 returnsthis
itself. Idempotent.- Since:
- 15.0
-
getComponentType
public final TypeToken<?> getComponentType()
Returns the array component type if this type represents an array (int[]
,T[]
,<? extends Map<String, Integer>[]>
etc.), or elsenull
is returned.
-
method
public final Invokable<T,java.lang.Object> method(java.lang.reflect.Method method)
- Since:
- 14.0
-
constructor
public final Invokable<T,T> constructor(java.lang.reflect.Constructor<?> constructor)
- Since:
- 14.0
-
equals
public boolean equals(java.lang.Object o)
Returns true ifo
is anotherTypeToken
that represents the sameType
.- Overrides:
equals
in classjava.lang.Object
-
hashCode
public int hashCode()
- Overrides:
hashCode
in classjava.lang.Object
-
toString
public java.lang.String toString()
- Overrides:
toString
in classjava.lang.Object
-
writeReplace
protected java.lang.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 likeTypeToInstanceMap
.
-
someRawTypeIsSubclassOf
private boolean someRawTypeIsSubclassOf(java.lang.Class<?> superclass)
-
isSubtypeOfParameterizedType
private boolean isSubtypeOfParameterizedType(java.lang.reflect.ParameterizedType supertype)
-
isSubtypeOfArrayType
private boolean isSubtypeOfArrayType(java.lang.reflect.GenericArrayType supertype)
-
isSupertypeOfArray
private boolean isSupertypeOfArray(java.lang.reflect.GenericArrayType subtype)
-
is
private boolean is(java.lang.reflect.Type formalType, java.lang.reflect.TypeVariable<?> declaration)
A.is(B)
is defined asFoo<A>.isSubtypeOf(Foo<B>)
.Specifically, returns true if any of the following conditions is met:
- 'this' and
formalType
are equal. - 'this' and
formalType
have equal canonical form. formalType
is<? extends Foo>
and 'this' is a subtype ofFoo
.formalType
is<? super Foo>
and 'this' is a supertype ofFoo
.
Enum<? extends Enum<E>>
canonicalizes toEnum<?>
whereE
is the type variable declared on theEnum
class declaration. It's technically not true thatFoo<Enum<? extends Enum<E>>>
is a subtype ofFoo<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
- isFoo<formalType>
a supertype ofFoo<T>
?declaration
- The type variable in the context of a parameterized type. Used to infer type bound whenformalType
is a wildcard with implicit upper bound.
- 'this' and
-
canonicalizeTypeArg
private static java.lang.reflect.Type canonicalizeTypeArg(java.lang.reflect.TypeVariable<?> declaration, java.lang.reflect.Type typeArg)
In reflection,Foo<?>.getUpperBounds()[0]
is alwaysObject.class
, even when Foo is defined asFoo<T extends String>
. Thus directly calling<?>.is(String.class)
will return false. To mitigate, we canonicalize wildcards by enforcing the following invariants:canonicalize(t)
always produces the equal result for equivalent types. For example bothEnum<?>
andEnum<? extends Enum<?>>
canonicalize toEnum<? extends Enum<E>
.canonicalize(t)
produces a "literal" supertype of t. For example:Enum<? extends Enum<?>>
canonicalizes toEnum<?>
, which is a supertype (if we disregard the upper bound is implicitly an Enum too).- If
canonicalize(A) == canonicalize(B)
, thenFoo<A>.isSubtypeOf(Foo<B>)
and vice versa. i.e.A.is(B)
andB.is(A)
. canonicalize(canonicalize(A)) == canonicalize(A)
.
-
canonicalizeWildcardsInType
private static java.lang.reflect.Type canonicalizeWildcardsInType(java.lang.reflect.Type type)
-
canonicalizeWildcardType
private static java.lang.reflect.WildcardType canonicalizeWildcardType(java.lang.reflect.TypeVariable<?> declaration, java.lang.reflect.WildcardType type)
-
canonicalizeWildcardsInParameterizedType
private static java.lang.reflect.ParameterizedType canonicalizeWildcardsInParameterizedType(java.lang.reflect.ParameterizedType type)
-
every
private static TypeToken.Bounds every(java.lang.reflect.Type[] bounds)
-
any
private static TypeToken.Bounds any(java.lang.reflect.Type[] bounds)
-
getRawTypes
private ImmutableSet<java.lang.Class<? super T>> getRawTypes()
-
isOwnedBySubtypeOf
private boolean isOwnedBySubtypeOf(java.lang.reflect.Type supertype)
-
getOwnerTypeIfPresent
private java.lang.reflect.Type getOwnerTypeIfPresent()
Returns the owner type of aParameterizedType
or enclosing class of aClass
, or null otherwise.
-
toGenericType
static <T> TypeToken<? extends T> toGenericType(java.lang.Class<T> cls)
Returns the type token representing the generic type declaration ofcls
. For example:TypeToken.getGenericType(Iterable.class)
returnsIterable<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(java.lang.Class<? super T> supertype, java.lang.reflect.Type[] upperBounds)
-
getSubtypeFromLowerBounds
private TypeToken<? extends T> getSubtypeFromLowerBounds(java.lang.Class<?> subclass, java.lang.reflect.Type[] lowerBounds)
-
getArraySupertype
private TypeToken<? super T> getArraySupertype(java.lang.Class<? super T> supertype)
-
resolveTypeArgsForSubclass
private java.lang.reflect.Type resolveTypeArgsForSubclass(java.lang.Class<?> subclass)
-
newArrayClassOrGenericArrayType
private static java.lang.reflect.Type newArrayClassOrGenericArrayType(java.lang.reflect.Type componentType)
Creates an array class ifcomponentType
is a class, or else, aGenericArrayType
. This is what Java7 does for generic array type parameters.
-
-