@Beta public abstract class TypeToken<T> extends TypeCapture<T> implements java.io.Serializable
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:
Type
obtained via reflection. For example:
TypeToken.of(method.getGenericReturnType())
.
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();
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.
Modifier and Type | Class and 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 that
T is or is a subtype of. |
Modifier and Type | Field and Description |
---|---|
private java.lang.reflect.Type |
runtimeType |
private TypeResolver |
typeResolver
Resolver for resolving types with
runtimeType as context. |
Modifier | Constructor and Description |
---|---|
protected |
TypeToken()
Constructs a new type token of
T . |
protected |
TypeToken(java.lang.Class<?> declaringClass)
Constructs a new type token of
T while resolving free type variables in the context of
declaringClass . |
private |
TypeToken(java.lang.reflect.Type type) |
Modifier and Type | Method and 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) |
Invokable<T,T> |
constructor(java.lang.reflect.Constructor<?> constructor)
|
boolean |
equals(java.lang.Object o)
Returns true if
o is another TypeToken that represents the same Type . |
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 else null is returned. |
(package private) ImmutableList<TypeToken<? super T>> |
getGenericInterfaces()
Returns the generic interfaces that this type directly
implements . |
(package private) TypeToken<? super T> |
getGenericSuperclass()
Returns the generic superclass of this type or
null if the type represents
Object or an interface. |
private java.lang.reflect.Type |
getOwnerTypeIfPresent()
Returns the owner type of a
ParameterizedType or enclosing class of a Class ,
or null otherwise. |
java.lang.Class<? super T> |
getRawType()
Returns the raw type of
T . |
private ImmutableSet<java.lang.Class<? super T>> |
getRawTypes() |
TypeToken<? extends T> |
getSubtype(java.lang.Class<?> subclass)
Returns subtype of
this with subclass 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 of
superclass . |
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)
Return true if any of the following conditions is met:
'this' and
formalType are equal
formalType is <? extends Foo> and 'this' is a subtype of Foo
formalType is <? super Foo> and 'this' is a supertype of Foo
|
boolean |
isArray()
Returns true if this type is known to be an array type, such as
int[] , 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 (including
void ). |
boolean |
isSubtypeOf(java.lang.reflect.Type supertype)
Returns true if this type is a subtype of the given
type . |
boolean |
isSubtypeOf(TypeToken<?> type)
Returns true if this type is a subtype of the given
type . |
private boolean |
isSubtypeOfArrayType(java.lang.reflect.GenericArrayType supertype) |
private boolean |
isSubtypeOfParameterizedType(java.lang.reflect.ParameterizedType supertype) |
boolean |
isSupertypeOf(java.lang.reflect.Type type)
Returns true if this type is a supertype of the given
type . |
boolean |
isSupertypeOf(TypeToken<?> type)
Returns true if this type is a supertype of the given
type . |
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 if
componentType is a class, or else, a
GenericArrayType . |
static <T> TypeToken<T> |
of(java.lang.Class<T> type)
Returns an instance of type token that wraps
type . |
static TypeToken<?> |
of(java.lang.reflect.Type type)
Returns an instance of type token that wraps
type . |
(package private) TypeToken<T> |
rejectTypeVariables()
Ensures that this type token doesn't contain type variables, which can cause unchecked type
errors for callers like
TypeToInstanceMap . |
private java.lang.reflect.Type[] |
resolveInPlace(java.lang.reflect.Type[] types) |
private TypeToken<?> |
resolveSupertype(java.lang.reflect.Type type) |
TypeToken<?> |
resolveType(java.lang.reflect.Type type)
Resolves the given
type 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 of
cls . |
java.lang.String |
toString() |
TypeToken<T> |
unwrap()
Returns the corresponding primitive type if this is a wrapper type; otherwise returns
this itself. |
<X> TypeToken<T> |
where(TypeParameter<X> typeParam,
java.lang.Class<X> typeArg)
Returns a new
TypeToken where type variables represented by typeParam are
substituted by typeArg . |
<X> TypeToken<T> |
where(TypeParameter<X> typeParam,
TypeToken<X> typeArg)
Returns a new
TypeToken where type variables represented by typeParam are
substituted by typeArg . |
TypeToken<T> |
wrap()
Returns the corresponding wrapper type if this is a primitive type; otherwise returns
this itself. |
protected java.lang.Object |
writeReplace()
Implemented to support serialization of subclasses.
|
capture
private final java.lang.reflect.Type runtimeType
private transient TypeResolver typeResolver
runtimeType
as context.protected TypeToken()
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>>() {};
protected TypeToken(java.lang.Class<?> declaringClass)
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
private TypeToken(java.lang.reflect.Type type)
public static <T> TypeToken<T> of(java.lang.Class<T> type)
type
.public static TypeToken<?> of(java.lang.reflect.Type type)
type
.public final java.lang.Class<? super T> getRawType()
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:
T
is a Class
itself, T
itself is returned.
T
is a ParameterizedType
, the raw type of the parameterized type is
returned.
T
is a GenericArrayType
, the returned type is the corresponding array
class. For example: List<Integer>[] => List[]
.
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
.
public final java.lang.reflect.Type getType()
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);
}
X
- The parameter typetypeParam
- the parameter type variabletypeArg
- the actual type to substitutepublic final <X> TypeToken<T> where(TypeParameter<X> typeParam, java.lang.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);
}
X
- The parameter typetypeParam
- the parameter type variabletypeArg
- the actual type to substitutepublic final TypeToken<?> resolveType(java.lang.reflect.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
private java.lang.reflect.Type[] resolveInPlace(java.lang.reflect.Type[] types)
private TypeToken<?> resolveSupertype(java.lang.reflect.Type type)
@Nullable final TypeToken<? super T> getGenericSuperclass()
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.
@Nullable private TypeToken<? super T> boundAsSuperclass(java.lang.reflect.Type bound)
final ImmutableList<TypeToken<? super T>> getGenericInterfaces()
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.
private ImmutableList<TypeToken<? super T>> boundsAsInterfaces(java.lang.reflect.Type[] bounds)
public final TypeToken.TypeSet getTypes()
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).
public final TypeToken<? super T> getSupertype(java.lang.Class<? super T> superclass)
superclass
. For example, if this is
ArrayList<String>
, Iterable<String>
is returned given the input
Iterable.class
.public final TypeToken<? extends T> getSubtype(java.lang.Class<?> subclass)
this
with subclass
as the raw class. For example, if this is
Iterable<String>
and subclass
is List
, List<String>
is
returned.public final boolean isSupertypeOf(TypeToken<?> type)
type
. "Supertype" is defined
according to
the rules for
type arguments introduced with Java generics.public final boolean isSupertypeOf(java.lang.reflect.Type type)
type
. "Supertype" is defined
according to
the rules for
type arguments introduced with Java generics.public final boolean isSubtypeOf(TypeToken<?> type)
type
. "Subtype" is defined
according to
the rules for
type arguments introduced with Java generics.public final boolean isSubtypeOf(java.lang.reflect.Type supertype)
type
. "Subtype" is defined
according to
the rules for
type arguments introduced with Java generics.public final boolean isArray()
int[]
, T[]
,
<? extends Map<String, Integer>[]>
etc.public final boolean isPrimitive()
void
).public final TypeToken<T> wrap()
this
itself. Idempotent.private boolean isWrapper()
public final TypeToken<T> unwrap()
this
itself. Idempotent.@Nullable public final TypeToken<?> getComponentType()
int[]
, T[]
,
<? extends Map<String, Integer>[]>
etc.), or else null
is returned.public final Invokable<T,java.lang.Object> method(java.lang.reflect.Method method)
public final Invokable<T,T> constructor(java.lang.reflect.Constructor<?> constructor)
public boolean equals(@Nullable java.lang.Object o)
o
is another TypeToken
that represents the same Type
.equals
in class java.lang.Object
public int hashCode()
hashCode
in class java.lang.Object
public java.lang.String toString()
toString
in class java.lang.Object
protected java.lang.Object writeReplace()
final TypeToken<T> rejectTypeVariables()
TypeToInstanceMap
.private boolean someRawTypeIsSubclassOf(java.lang.Class<?> superclass)
private boolean isSubtypeOfParameterizedType(java.lang.reflect.ParameterizedType supertype)
private boolean isSubtypeOfArrayType(java.lang.reflect.GenericArrayType supertype)
private boolean isSupertypeOfArray(java.lang.reflect.GenericArrayType subtype)
private boolean is(java.lang.reflect.Type formalType)
formalType
are equal
formalType
is <? extends Foo>
and 'this' is a subtype of Foo
formalType
is <? super Foo>
and 'this' is a supertype of Foo
private static TypeToken.Bounds every(java.lang.reflect.Type[] bounds)
private static TypeToken.Bounds any(java.lang.reflect.Type[] bounds)
private ImmutableSet<java.lang.Class<? super T>> getRawTypes()
private boolean isOwnedBySubtypeOf(java.lang.reflect.Type supertype)
@Nullable private java.lang.reflect.Type getOwnerTypeIfPresent()
ParameterizedType
or enclosing class of a Class
,
or null otherwise.static <T> TypeToken<? extends T> toGenericType(java.lang.Class<T> cls)
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.
private TypeToken<? super T> getSupertypeFromUpperBounds(java.lang.Class<? super T> supertype, java.lang.reflect.Type[] upperBounds)
private TypeToken<? extends T> getSubtypeFromLowerBounds(java.lang.Class<?> subclass, java.lang.reflect.Type[] lowerBounds)
private TypeToken<? super T> getArraySupertype(java.lang.Class<? super T> supertype)
private java.lang.reflect.Type resolveTypeArgsForSubclass(java.lang.Class<?> subclass)
private static java.lang.reflect.Type newArrayClassOrGenericArrayType(java.lang.reflect.Type componentType)
componentType
is a class, or else, a
GenericArrayType
. This is what Java7 does for generic array type parameters.