public final class GenericsUtils
extends java.lang.Object
| Modifier and Type | Method and Description |
|---|---|
static java.util.LinkedHashMap<java.lang.String,java.lang.reflect.Type> |
createGenericsMap(java.lang.Class<?> type,
java.util.List<? extends java.lang.reflect.Type> generics)
Converts type's known generics collection into generics map, suitable for usage with the api.
|
static java.util.Map<java.lang.String,java.lang.reflect.Type> |
extractOwnerGenerics(java.lang.Class<?> type,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
It is important to keep possible outer class generics, because they may be used in type declarations.
|
static java.util.Map<java.lang.String,java.lang.reflect.Type> |
extractTypeGenerics(java.lang.Class<?> type,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
Generics declaration may contain type's generics together with outer class generics (if type is inner class).
|
static java.lang.reflect.TypeVariable |
findIncompatibleVariable(java.lang.reflect.Type type,
java.lang.Class<?> context,
GenericDeclarationScope contextScope,
java.lang.reflect.GenericDeclaration contextSource)
Generics visibility (from inside context class):
Generics declared on class
Generics declared on outer class (if current is inner)
Constructor generics (if inside constructor)
Method generics (if inside method)
.
|
static java.util.List<java.lang.reflect.TypeVariable> |
findVariables(java.lang.reflect.Type type)
Searches for generic variable declarations in type.
|
static java.lang.Class<?> |
getDeclarationClass(java.lang.reflect.GenericDeclaration source) |
static java.lang.Class<?> |
getDeclarationClass(java.lang.reflect.TypeVariable variable) |
static java.lang.reflect.Type[] |
getGenerics(java.lang.reflect.Type type,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
If type is a variable, looks actual variable type, if it contains generics.
|
static java.lang.Class<?> |
getReturnClass(java.lang.reflect.Method method,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
Called to properly resolve return type of root finder or inherited finder method.
|
static java.util.List<java.lang.reflect.TypeVariable> |
orderVariablesForResolution(java.util.List<java.lang.reflect.TypeVariable> variables)
Order variables for consequent variables resolution (to support reverse order declaration cases).
|
static java.lang.Class<?> |
resolveClass(java.lang.reflect.Type type,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
Resolves top class for provided type (for example, for generified classes like
List<T> it
returns base type List). |
static java.util.List<java.lang.Class<?>> |
resolveClasses(java.lang.reflect.Type[] types,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
Resolve classes of provided types.
|
static java.util.List<java.lang.Class<?>> |
resolveGenericsOf(java.lang.reflect.Type type,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
Called to properly resolve generified type (e.g. generified method return).
|
static java.lang.reflect.Type[] |
resolveTypeVariables(java.lang.reflect.Type[] types,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
Shortcut for
resolveTypeVariables(Type, Map) to process multiple types at once. |
static java.lang.reflect.Type |
resolveTypeVariables(java.lang.reflect.Type type,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
Resolve type generics.
|
static java.lang.Class[] |
resolveUpperBounds(java.lang.reflect.Type type,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
In most cases
resolveClass(Type, Map) could be used instead (for simplicity). |
public static java.lang.Class<?> getReturnClass(java.lang.reflect.Method method,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
Note: may return primitive because it might be important to differentiate actual value.
Use TypeUtils.wrapPrimitive(Class) to box possible primitive, if required.
method - method to analyzegenerics - generics resolution map for method class (will be null for root)public static java.lang.reflect.Type[] getGenerics(java.lang.reflect.Type type,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
ParameterizedType return actual type parameters, for simple class returns raw class generics.
Note: returned generics may contain variables inside!
type - type to get generics ofgenerics - context generics mappublic static java.util.List<java.lang.Class<?>> resolveGenericsOf(java.lang.reflect.Type type,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
List<T> it will return type of T.
If called on class (e.g. List) then return raw generic definition (upper bounds).
type - type to analyzegenerics - root class generics mappingUnknownGenericException - when found generic not declared on type (e.g. method generic)public static java.lang.Class<?> resolveClass(java.lang.reflect.Type type,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
List<T> it
returns base type List).
Note: may return primitive because it might be important to differentiate actual value.
Use TypeUtils.wrapPrimitive(Class) to box possible primitive, if required.
type - type to resolvegenerics - root class generics mappingUnknownGenericException - when found generic not declared on type (e.g. method generic)public static java.util.List<java.lang.Class<?>> resolveClasses(java.lang.reflect.Type[] types,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
Note: may return primitives because it might be important to differentiate actual value.
Use TypeUtils.wrapPrimitive(Class) to box possible primitive, if required.
types - types to resolvegenerics - type genericspublic static java.lang.Class[] resolveUpperBounds(java.lang.reflect.Type type,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
resolveClass(Type, Map) could be used instead (for simplicity). This method will
only return different result for wildcards inside resolved types (where generics are replaced
resolveTypeVariables(Type, Map)). Also, in contrast to resolveClass(Type, Map),
method will replace primitive types with wrappers (int -> Integer etc.) because this method is used mostly for
comparison logic and avoiding primitives simplifies it.
Wildcards are used to store raw resolution of generic declaration T extends Number & Comparable
(but ? extends Number & Comparable is not allowed in java). Only for this case multiple bounds
will be returned.
That precision may be important only for exact types compatibility logic.
type - type to resolve upper boundsgenerics - known genericsUnknownGenericException - when found generic not declared on type (e.g. method generic)supplement check methodpublic static java.lang.reflect.Type resolveTypeVariables(java.lang.reflect.Type type,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
TypeVariable and returned
will be simple Class (resolved generic value).
Special handling for ExplicitTypeVariable - this kind of type variable is not resolved and not
throw exception as unknown generic (thought as resolved type). This may be used for cases when type
variable must be preserved (like generics tracking or custom to string).
Note that upper bounded wildcards are flattened to simple type (? extends Somthing -> Something as
upper bounded wildcards are not useful at runtime. The only exception is wildcard with multiple bounds
(repackaged declaration T extends A&B). Wildcards with Object as bound are also flattened
(List<? extends Object> --> List<Object>, List<?> --> List<Object>,
List<? super Object> --> List<Object>.
type - type to resolvegenerics - root class generics mappingUnknownGenericException - when found generic not declared on type (e.g. method generic)public static java.lang.reflect.Type[] resolveTypeVariables(java.lang.reflect.Type[] types,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
resolveTypeVariables(Type, Map) to process multiple types at once.types - types to replace named generics ingenerics - known genericspublic static java.util.Map<java.lang.String,java.lang.reflect.Type> extractOwnerGenerics(java.lang.Class<?> type,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
class Outer<T, K> {
// outer generic T hidden
class Inner<T> {}
}
In order to recover possibly missed outer generics use extractTypeGenerics(type, resultedMap)
(may be required for proper owner type to string printing with all generics).type - typegenerics - all type's context generics (self + outer class)public static java.util.Map<java.lang.String,java.lang.reflect.Type> extractTypeGenerics(java.lang.Class<?> type,
java.util.Map<java.lang.String,java.lang.reflect.Type> generics)
In case when type's generic is not mentioned in map - it will be resolved from variable declaration.
type - typegenerics - all type's context generics (self + outer class)A<T, K> -> T, K) or empty map if no generics declared on typepublic static java.lang.Class<?> getDeclarationClass(java.lang.reflect.TypeVariable variable)
variable - generic variablepublic static java.lang.Class<?> getDeclarationClass(java.lang.reflect.GenericDeclaration source)
source - generic declaration source (could be null)public static java.util.LinkedHashMap<java.lang.String,java.lang.reflect.Type> createGenericsMap(java.lang.Class<?> type,
java.util.List<? extends java.lang.reflect.Type> generics)
Note that if provided class is inner class then outer class generics will be added to the map to avoid
unknown generics while using api with this map
(see GenericsResolutionUtils.fillOuterGenerics(Type, LinkedHashMap, Map)).
type - type to build generics map forgenerics - known generics (assumed in correct order)java.lang.IllegalArgumentException - if type's generics count don't match provided listpublic static java.lang.reflect.TypeVariable findIncompatibleVariable(java.lang.reflect.Type type,
java.lang.Class<?> context,
GenericDeclarationScope contextScope,
java.lang.reflect.GenericDeclaration contextSource)
type - type to checkcontext - current context classcontextScope - current context scope (class, method, constructor)contextSource - context source object (required for method and constructor scopes)public static java.util.List<java.lang.reflect.TypeVariable> orderVariablesForResolution(java.util.List<java.lang.reflect.TypeVariable> variables)
T extends List<K>, K, P extends Collection<T> must be resolved as 2, 1, 3 or
T extends List<D>, D extends Collection<P>, P must be resolved as 3, 2, 1 or
T extends List<D>, P, D extends Collection<P> must be resolved as 2, 3, 1
(otherwise resolution will fail due to unknown generic).
Note: incomplete set of variables could be provided: method order only provided vars, ignoring all other variables (assuming they are known). This allows using this method inside error handler (in order to process only not recognized vars).
variables - variables to orderpublic static java.util.List<java.lang.reflect.TypeVariable> findVariables(java.lang.reflect.Type type)
List<T> it will find "T", in Some<Long, T, List<K> "T" and "K".type - type to analyze.