public final class TypeUtils
extends java.lang.Object
| Modifier and Type | Method and Description |
|---|---|
static java.lang.reflect.Type |
getMoreSpecificType(java.lang.reflect.Type one,
java.lang.reflect.Type two)
Not resolved type variables are resolved to Object.
|
static java.lang.reflect.Type |
getOuter(java.lang.reflect.Type type)
May return
ParameterizedType if incoming type contains owner declaration like
Outer<String>.Inner field (field.getGenericType() will contain outer generic). |
static boolean |
isAssignable(java.lang.reflect.Type what,
java.lang.reflect.Type toType)
Checks if type could be casted to type.
|
static boolean |
isAssignableBounds(java.lang.Class[] one,
java.lang.Class[] two)
Method is useful for wildcards processing.
|
static boolean |
isCompatible(java.lang.reflect.Type one,
java.lang.reflect.Type two)
Check if types are compatible: types must be equal or one extend another.
|
static boolean |
isInner(java.lang.reflect.Type type)
class Owner<T> {
class Inner {
T field; // parent generic reference
}
}. |
static boolean |
isMoreSpecific(java.lang.reflect.Type what,
java.lang.reflect.Type comparingTo)
Checks if type is more specific than provided one.
|
static java.lang.Class<?> |
wrapPrimitive(java.lang.Class<?> type) |
public static java.lang.Class<?> wrapPrimitive(java.lang.Class<?> type)
type - class to wrappublic static boolean isMoreSpecific(java.lang.reflect.Type what,
java.lang.reflect.Type comparingTo)
ArrayList is more specific then
List or List<Integer> is more specific then List<Object>.
Note that comparison logic did not follow all java rules (especially wildcards) as some rules are not important at runtime.
Not resolved type variables are resolved to Object. Object is considered as unknown type: everything
is assignable to Object and Object is assignable to everything.
List == List<Object> == List<?> == List<? super Object> == List<? extends Object>.
For lower bounded wildcards more specific wildcard contains lower bound: ? extends Number is
more specific then ? extends Integer. Also, lower bounded wildcard is always more specific then
Object.
Not the same as isAssignable(Type, Type). For example:
isAssignable(List, List<String>) == true, but isMoreSpecific(List, List<String>) == false.
Primitive types are checked as wrappers (for example, int is more specific then Number).
what - type to checkcomparingTo - type to compare tojava.lang.IllegalArgumentException - when types are not compatiblefor implementation detailspublic static boolean isAssignable(java.lang.reflect.Type what,
java.lang.reflect.Type toType)
T<String, Object> is assignable to T<String, String> as Object considered as unknown
type and so could be compatible (in opposite way is also assignable as anything is assignable to Object).
Of course, actual value used instead of Object may be incompatible, but method intended only to check all available types information (if nothing stops me yet). Use exact types to get more correct result. Example usage scenario: check field type before trying to assign something with reflection.
Java wildcard rules are generally not honored because at runtime they are meaningless.
List == List<Object> == List<? super Object> == List<? extends Object>. All upper bounds are used for
comparison (multiple upper bounds in wildcard could be from repackaging of generic declaration
T<extends A&B>. Lower bounds are taken into account as: if both have lower bound then
right's type bound must be higher (? extends Number and ? extends Integer). If only left
type is lower bounded wildcard then it is not assignable (except Object).
Primitive types are checked as wrappers (for example, int is more specific then Number).
what - type to checktoType - type to check assignability forfor implementation detailspublic static boolean isAssignableBounds(java.lang.Class[] one,
java.lang.Class[] two)
T extends Something & Comparable stored as wildcard ? extends Something & Comparable).
Use only when exact precision is required, otherwise you can use just first classes from both
(first upper bound) as multiple bounds case is quite rare.
Bounds are assignable if one class from left bound is assignable to all types in right bound. For example,
Number & Serializable and Number assignableInteger & Serializable and Number & Comparable assignableInteger and Number & Serializable not assignable
Object is assumed as unknown type. Object could be assigned to any type and any type could be assigned to
Object. Closest analogy from java rules is no generics: for example, List without generics could be
assigned anywhere (List<Integer> = List - valid java code).
No primitives expected: no special wrapping performed (as supplement method
GenericsUtils.resolveUpperBounds(Type, Map) already handle primitives).
one - first boundtwo - second boundsupplement resolution methodpublic static java.lang.reflect.Type getMoreSpecificType(java.lang.reflect.Type one,
java.lang.reflect.Type two)
one - first typetwo - second typeisMoreSpecific(Type, Type)public static boolean isCompatible(java.lang.reflect.Type one,
java.lang.reflect.Type two)
Not resolved type variables are resolved to Object.
Primitive types are checked as wrappers (for example, int is more specific then Number).
one - first typetwo - second typefor implementation detailspublic static boolean isInner(java.lang.reflect.Type type)
class Owner<T> {
class Inner {
T field; // parent generic reference
}
}.type - class to checkpublic static java.lang.reflect.Type getOuter(java.lang.reflect.Type type)
ParameterizedType if incoming type contains owner declaration like
Outer<String>.Inner field (field.getGenericType() will contain outer generic).type - inner class (probably)