Top Description Inners Fields Constructors Methods
com.google.common.reflect

public final Class TypeResolver

extends Object
Class Inheritance
Annotations
@ElementTypesAreNonnullByDefault
Static Imports
com.google.common.base.Preconditions.checkArgument, .Preconditions.checkNotNull, .Preconditions.checkState, java.util.Arrays.asList

An object of this class encapsulates type mappings from type variables. Mappings are established with where and types are resolved using resolveType.

Note that usually type mappings are already implied by the static type hierarchy (for example, the E type variable declared by class List naturally maps to String in the context of class MyStringList implements List<String>). In such case, prefer to use TypeToken#resolveType since it's simpler and more type safe. This class should only be used when the type mapping isn't implied by the static type hierarchy, but provided through other means such as an annotation or external configuration file.

Author
Ben Yu
Since
15.0

Nested and Inner Type Summary

Modifier and TypeClass and Description
private static class
private static class
TypeResolver.TypeTable

A TypeTable maintains mapping from TypeVariable to types.

pack-priv static class
TypeResolver.TypeVariableKey

Wraps around TypeVariable<?

private static class

Field Summary

Modifier and TypeField and Description
private final TypeResolver.TypeTable

Constructor Summary

AccessConstructor and Description
public
private

Method Summary

Modifier and TypeMethod and Description
pack-priv static TypeResolver
covariantly(Type contextType)

Returns a resolver that resolves types "covariantly".

private static <T> T
expectArgument(Class<T> type, Object arg)

pack-priv static TypeResolver
invariantly(Type contextType)

Returns a resolver that resolves types "invariantly".

private static void
private Type
private ParameterizedType
public Type
resolveType(Type type)

Resolves all type variables in type and all downstream types and returns a corresponding type with type variables resolved.

private Type[]
resolveTypes(Type[] types)

pack-priv Type[]
private WildcardType
public TypeResolver
where(Type
The type whose type variables or itself is mapped to other type(s). It's almost always a bug if formal isn't a type variable and contains no type variable. Make sure you are passing the two parameters in the right order.
formal
,
Type
The type that the formal type variable(s) are mapped to. It can be or contain yet other type variables, in which case these type variables will be further resolved if corresponding mappings exist in the current TypeResolver instance.
actual
)

Returns a new TypeResolver with type variables in formal mapping to types in actual.

pack-priv TypeResolver
where(Map<TypeResolver.TypeVariableKey, ? extends Type> mappings)

Returns a new TypeResolver with variable mapping to type.

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

typeTableback to summary
private final TypeResolver.TypeTable typeTable

Constructor Detail

TypeResolverback to summary
public TypeResolver()
TypeResolverback to summary
private TypeResolver(TypeResolver.TypeTable typeTable)

Method Detail

covariantlyback to summary
pack-priv static TypeResolver covariantly(Type contextType)

Returns a resolver that resolves types "covariantly".

For example, when resolving List<T> in the context of ArrayList<?>, <T> is covariantly resolved to <?> such that return type of List::get is <?>.

expectArgumentback to summary
private static <T> T expectArgument(Class<T> type, Object arg)
invariantlyback to summary
pack-priv static TypeResolver invariantly(Type contextType)

Returns a resolver that resolves types "invariantly".

For example, when resolving List<T> in the context of ArrayList<?>, <T> cannot be invariantly resolved to <?> because otherwise the parameter type of List::set will be <?> and it'll falsely say any object can be passed into ArrayList<?>::set.

Instead, <?> will be resolved to a capture in the form of a type variable <capture-of-? extends Object>, effectively preventing set from accepting any type.

populateTypeMappingsback to summary
private static void populateTypeMappings(Map<TypeResolver.TypeVariableKey, Type> mappings, Type from, Type to)
resolveGenericArrayTypeback to summary
private Type resolveGenericArrayType(GenericArrayType type)
resolveParameterizedTypeback to summary
private ParameterizedType resolveParameterizedType(ParameterizedType type)
resolveTypeback to summary
public Type resolveType(Type type)

Resolves all type variables in type and all downstream types and returns a corresponding type with type variables resolved.

resolveTypesback to summary
private Type[] resolveTypes(Type[] types)
resolveTypesInPlaceback to summary
pack-priv Type[] resolveTypesInPlace(Type[] types)
resolveWildcardTypeback to summary
private WildcardType resolveWildcardType(WildcardType type)
whereback to summary
public TypeResolver where(Type formal, Type actual)

Returns a new TypeResolver with type variables in formal mapping to types in actual.

For example, if formal is a TypeVariable T, and actual is String.class, then new TypeResolver().where(formal, actual) will resolve ParameterizedType List<T> to List<String>, and resolve Map<T, Something> to Map<String, Something> etc. Similarly, formal and actual can be Map<K, V> and Map<String, Integer> respectively, or they can be E[] and String[] respectively, or even any arbitrary combination thereof.

Parameters
formal:Type

The type whose type variables or itself is mapped to other type(s). It's almost always a bug if formal isn't a type variable and contains no type variable. Make sure you are passing the two parameters in the right order.

actual:Type

The type that the formal type variable(s) are mapped to. It can be or contain yet other type variables, in which case these type variables will be further resolved if corresponding mappings exist in the current TypeResolver instance.

whereback to summary
pack-priv TypeResolver where(Map<TypeResolver.TypeVariableKey, ? extends Type> mappings)

Returns a new TypeResolver with variable mapping to type.

com.google.common.reflect back to summary

private final Class TypeResolver.TypeMappingIntrospector

extends TypeVisitor
Class Inheritance

Field Summary

Modifier and TypeField and Description
private final Map<TypeResolver.TypeVariableKey, Type>

Constructor Summary

AccessConstructor and Description
private

Method Summary

Modifier and TypeMethod and Description
pack-priv static ImmutableMap<TypeResolver.TypeVariableKey, Type>
getTypeMappings(Type contextType)

Returns type mappings using type parameters and type arguments found in the generic superclass and the super interfaces of contextClass.

private void
pack-priv void
pack-priv void
pack-priv void
pack-priv void
Inherited from com.google.common.reflect.TypeVisitor:
visitvisitGenericArrayType

Field Detail

mappingsback to summary
private final Map<TypeResolver.TypeVariableKey, Type> mappings

Constructor Detail

TypeMappingIntrospectorback to summary
private TypeMappingIntrospector()

Method Detail

getTypeMappingsback to summary
pack-priv static ImmutableMap<TypeResolver.TypeVariableKey, Type> getTypeMappings(Type contextType)

Returns type mappings using type parameters and type arguments found in the generic superclass and the super interfaces of contextClass.

mapback to summary
private void map(TypeResolver.TypeVariableKey var, Type arg)
visitClassback to summary
pack-priv void visitClass(Class<?> clazz)

Overrides com.google.common.reflect.TypeVisitor.visitClass.

Annotations
@Override
visitParameterizedTypeback to summary
pack-priv void visitParameterizedType(ParameterizedType parameterizedType)

Overrides com.google.common.reflect.TypeVisitor.visitParameterizedType.

Annotations
@Override
visitTypeVariableback to summary
pack-priv void visitTypeVariable(TypeVariable<?> t)

Overrides com.google.common.reflect.TypeVisitor.visitTypeVariable.

Annotations
@Override
visitWildcardTypeback to summary
pack-priv void visitWildcardType(WildcardType t)

Overrides com.google.common.reflect.TypeVisitor.visitWildcardType.

Annotations
@Override
com.google.common.reflect back to summary

private Class TypeResolver.TypeTable

extends Object
Class Inheritance

A TypeTable maintains mapping from TypeVariable to types.

Field Summary

Modifier and TypeField and Description
private final ImmutableMap<TypeResolver.TypeVariableKey, Type>

Constructor Summary

AccessConstructor and Description
pack-priv
private

Method Summary

Modifier and TypeMethod and Description
pack-priv final Type
pack-priv Type
resolveInternal(TypeVariable<?> var, TypeResolver.TypeTable forDependants)

Resolves var using the encapsulated type mapping.

pack-priv final TypeResolver.TypeTable
where(Map<TypeResolver.TypeVariableKey, ? extends Type> mappings)

Returns a new TypeResolver with variable mapping to type.

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

mapback to summary
private final ImmutableMap<TypeResolver.TypeVariableKey, Type> map

Constructor Detail

TypeTableback to summary
pack-priv TypeTable()
TypeTableback to summary
private TypeTable(ImmutableMap<TypeResolver.TypeVariableKey, Type> map)

Method Detail

resolveback to summary
pack-priv final Type resolve(TypeVariable<?> var)
resolveInternalback to summary
pack-priv Type resolveInternal(TypeVariable<?> var, TypeResolver.TypeTable forDependants)

Resolves var using the encapsulated type mapping. If it maps to yet another non-reified type or has bounds, forDependants is used to do further resolution, which doesn't try to resolve any type variable on generic declarations that are already being resolved.

Should only be called and overridden by resolve(TypeVariable).

whereback to summary
pack-priv final TypeResolver.TypeTable where(Map<TypeResolver.TypeVariableKey, ? extends Type> mappings)

Returns a new TypeResolver with variable mapping to type.

com.google.common.reflect back to summary

pack-priv final Class TypeResolver.TypeVariableKey

extends Object
Class Inheritance

Wraps around TypeVariable<?> to ensure that any two type variables are equal as long as they are declared by the same java.lang.reflect.GenericDeclaration and have the same name, even if their bounds differ.

While resolving a type variable from a var -> type map, we don't care whether the type variable's bound has been partially resolved. As long as the type variable "identity" matches.

On the other hand, if for example we are resolving List<A extends B> to List<A extends String>, we need to compare that <A extends B> is unequal to <A extends String> in order to decide to use the transformed type instead of the original type.

Field Summary

Modifier and TypeField and Description
private final TypeVariable<?>

Constructor Summary

AccessConstructor and Description
pack-priv

Method Summary

Modifier and TypeMethod and Description
public boolean
equals(Object
the reference object with which to compare.
obj
)

Overrides java.lang.Object.equals.

Indicates whether some other object is "equal to" this one.
pack-priv boolean
equalsType(Type type)

Returns true if type is a TypeVariable with the same name and declared by the same GenericDeclaration.

private boolean
pack-priv static TypeResolver.TypeVariableKey
forLookup(Type t)

Wraps t in a TypeVariableKey if it's a type variable.

public int
hashCode()

Overrides java.lang.Object.hashCode.

Returns a hash code value for this object.
public String
toString()

Overrides java.lang.Object.toString.

Returns a string representation of the object.
Inherited from java.lang.Object:
clonefinalizegetClassnotifynotifyAllwaitwaitwait

Field Detail

varback to summary
private final TypeVariable<?> var

Constructor Detail

TypeVariableKeyback to summary
pack-priv TypeVariableKey(TypeVariable<?> var)

Method Detail

equalsback to summary
public boolean equals(Object obj)

Overrides java.lang.Object.equals.

Doc from java.lang.Object.equals.

Indicates whether some other object is "equal to" this one.

The equals method implements an equivalence relation on non-null object references:

  • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • For any non-null reference value x, x.equals(null) should return false.

An equivalence relation partitions the elements it operates on into equivalence classes; all the members of an equivalence class are equal to each other. Members of an equivalence class are substitutable for each other, at least for some purposes.

Parameters
obj:Object

the reference object with which to compare.

Returns:boolean

true if this object is the same as the obj argument; false otherwise.

Annotations
@Override
equalsTypeback to summary
pack-priv boolean equalsType(Type type)

Returns true if type is a TypeVariable with the same name and declared by the same GenericDeclaration.

equalsTypeVariableback to summary
private boolean equalsTypeVariable(TypeVariable<?> that)
forLookupback to summary
pack-priv static TypeResolver.TypeVariableKey forLookup(Type t)

Wraps t in a TypeVariableKey if it's a type variable.

Annotations
@CheckForNull
hashCodeback to summary
public int hashCode()

Overrides java.lang.Object.hashCode.

Doc from java.lang.Object.hashCode.

Returns a hash code value for this object. This method is supported for the benefit of hash tables such as those provided by java.util.HashMap.

The general contract of hashCode is:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
  • If two objects are equal according to the equals method, then calling the hashCode method on each of the two objects must produce the same integer result.
  • It is not required that if two objects are unequal according to the equals method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
Returns:int

a hash code value for this object

Annotations
@Override
toStringback to summary
public String toString()

Overrides java.lang.Object.toString.

Doc from java.lang.Object.toString.

Returns a string representation of the object.

Returns:String

a string representation of the object

Annotations
@Override
com.google.common.reflect back to summary

private Class TypeResolver.WildcardCapturer

extends Object
Class Inheritance

Field Summary

Modifier and TypeField and Description
private final AtomicInteger
pack-priv static final TypeResolver.WildcardCapturer

Constructor Summary

AccessConstructor and Description
private
private

Method Summary

Modifier and TypeMethod and Description
pack-priv final Type
capture(Type type)

pack-priv TypeVariable<?>
captureAsTypeVariable(Type[] upperBounds)

private Type
private TypeResolver.WildcardCapturer
private TypeResolver.WildcardCapturer
Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

idback to summary
private final AtomicInteger id
INSTANCEback to summary
pack-priv static final TypeResolver.WildcardCapturer INSTANCE

Constructor Detail

WildcardCapturerback to summary
private WildcardCapturer()
WildcardCapturerback to summary
private WildcardCapturer(AtomicInteger id)

Method Detail

captureback to summary
pack-priv final Type capture(Type type)
captureAsTypeVariableback to summary
pack-priv TypeVariable<?> captureAsTypeVariable(Type[] upperBounds)
captureNullableback to summary
private Type captureNullable(Type type)
Annotations
@CheckForNull
forTypeVariableback to summary
private TypeResolver.WildcardCapturer forTypeVariable(TypeVariable<?> typeParam)
notForTypeVariableback to summary
private TypeResolver.WildcardCapturer notForTypeVariable()