Class MethodKey
- java.lang.Object
-
- org.apache.commons.jexl3.internal.introspection.MethodKey
-
public final class MethodKey extends java.lang.Object
A method key usable by the introspector cache.This stores a method (or class) name and parameters.
This replaces the original key scheme which used to build the key by concatenating the method name and parameters class names as one string with the exception that primitive types were converted to their object class equivalents.
The key is still based on the same information, it is just wrapped in an object instead. Primitive type classes are converted to they object equivalent to make a key; int foo(int) and int foo(Integer) do generate the same key.
A key can be constructed either from arguments (array of objects) or from parameters (array of class). Roughly 3x faster than string key to access the map and uses less memory.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
MethodKey.AmbiguousException
Simple distinguishable exception, used when we run across ambiguous overloading.
-
Field Summary
Fields Modifier and Type Field Description private static java.util.Map<java.lang.Class<?>,java.lang.Class<?>[]>
CONVERTIBLES
Maps from primitive types to invocation compatible classes.private static int
HASH
The hash code constants.private int
hashCode
The hash code.private static int
INCOMPARABLE
A method/ctor doesn't match a previously compared one.private static int
LESS_SPECIFIC
whether a method/ctor is less specific than a previously compared one.private java.lang.String
method
The method name.private static int
MORE_SPECIFIC
whether a method/ctor is more specific than a previously compared one.private static java.lang.Class<?>[]
NOARGS
A marker for empty parameter list.private java.lang.Class<?>[]
params
The parameters.private static int
PRIMITIVE_SIZE
The initial size of the primitive conversion map.private static java.util.Map<java.lang.Class<?>,java.lang.Class<?>[]>
STRICT_CONVERTIBLES
Maps from primitive types to invocation compatible primitive types.
-
Constructor Summary
Constructors Constructor Description MethodKey(java.lang.reflect.Executable aMethod)
Creates a key from a method.MethodKey(java.lang.String aMethod, java.lang.Class<?>[] args)
Creates a key from a method name and a set of parameters.MethodKey(java.lang.String aMethod, java.lang.Object[] args)
Creates a key from a method name and a set of arguments.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description private static <T extends java.lang.reflect.Executable>
MethodKey.AmbiguousExceptionambiguousException(java.lang.Class<?>[] classes, java.lang.Iterable<T> applicables)
Creates an ambiguous exception.private static java.lang.Class<?>[]
asArray(java.lang.Class<?>... args)
Helper to build class arrays.java.lang.String
debugString()
Outputs a human-readable debug representation of this key.boolean
equals(java.lang.Object obj)
private static <T extends java.lang.reflect.Executable>
java.util.Deque<T>getApplicables(T[] methods, java.lang.Class<?>[] classes)
Returns all methods that are applicable to actual argument types.(package private) java.lang.String
getMethod()
Gets this key's method name.private <T extends java.lang.reflect.Executable>
TgetMostSpecific(T[] methods)
Gets the most specific method that is applicable to actual argument types.java.lang.reflect.Constructor<?>
getMostSpecificConstructor(java.lang.reflect.Constructor<?>[] methods)
Gets the most specific constructor that is applicable to the parameters of this key.java.lang.reflect.Method
getMostSpecificMethod(java.lang.reflect.Method[] methods)
Gets the most specific method that is applicable to the parameters of this key.(package private) java.lang.Class<?>[]
getParameters()
Gets this key's method parameter classes.int
hashCode()
private static <T extends java.lang.reflect.Executable>
booleanisApplicable(T method, java.lang.Class<?>[] actuals)
Returns true if the supplied method is applicable to actual argument types.private static boolean
isConvertible(java.lang.Class<?> formal, java.lang.Class<?> actual, boolean possibleVarArg)
static boolean
isInvocationConvertible(java.lang.Class<?> formal, java.lang.Class<?> actual, boolean possibleVarArg)
Determines whether a type represented by a class object is convertible to another type represented by a class object using a method invocation conversion, treating object types of primitive types as if they were primitive types (that is, a Boolean actual parameter type matches boolean primitive formal type).private static boolean
isInvocationConvertible(java.lang.Class<?> formal, java.lang.Class<?> type, boolean strict, boolean possibleVarArg)
Determines parameter-argument invocation compatibility.private static boolean
isPrimitive(java.lang.Class<?> c, boolean possibleVarArg)
Checks whether a parameter class is a primitive.private static boolean
isStrictConvertible(java.lang.Class<?> formal, java.lang.Class<?> actual, boolean possibleVarArg)
static boolean
isStrictInvocationConvertible(java.lang.Class<?> formal, java.lang.Class<?> actual, boolean possibleVarArg)
Determines whether a type represented by a class object is convertible to another type represented by a class object using a method invocation conversion, without matching object and primitive types.static boolean
isVarArgs(java.lang.reflect.Executable method)
Checks whether a method accepts a variable number of arguments.private static int
moreSpecific(java.lang.Class<?>[] a, java.lang.Class<?>[] c1, java.lang.Class<?>[] c2)
Determines which method signature (represented by a class array) is more specific.(package private) static java.lang.Class<?>
primitiveClass(java.lang.Class<?> parm)
Converts a primitive type to its corresponding class.java.lang.String
toString()
-
-
-
Field Detail
-
PRIMITIVE_SIZE
private static final int PRIMITIVE_SIZE
The initial size of the primitive conversion map.- See Also:
- Constant Field Values
-
NOARGS
private static final java.lang.Class<?>[] NOARGS
A marker for empty parameter list.
-
HASH
private static final int HASH
The hash code constants.- See Also:
- Constant Field Values
-
CONVERTIBLES
private static final java.util.Map<java.lang.Class<?>,java.lang.Class<?>[]> CONVERTIBLES
Maps from primitive types to invocation compatible classes.Considering the key as a parameter type, the value is the list of argument classes that are invocation compatible with the parameter. Example is Long is invocation convertible to long.
-
STRICT_CONVERTIBLES
private static final java.util.Map<java.lang.Class<?>,java.lang.Class<?>[]> STRICT_CONVERTIBLES
Maps from primitive types to invocation compatible primitive types.Considering the key as a parameter type, the value is the list of argument types that are invocation compatible with the parameter. Example is 'int' is invocation convertible to 'long'.
-
MORE_SPECIFIC
private static final int MORE_SPECIFIC
whether a method/ctor is more specific than a previously compared one.- See Also:
- Constant Field Values
-
LESS_SPECIFIC
private static final int LESS_SPECIFIC
whether a method/ctor is less specific than a previously compared one.- See Also:
- Constant Field Values
-
INCOMPARABLE
private static final int INCOMPARABLE
A method/ctor doesn't match a previously compared one.- See Also:
- Constant Field Values
-
hashCode
private final int hashCode
The hash code.
-
method
private final java.lang.String method
The method name.
-
params
private final java.lang.Class<?>[] params
The parameters.
-
-
Constructor Detail
-
MethodKey
MethodKey(java.lang.reflect.Executable aMethod)
Creates a key from a method.- Parameters:
aMethod
- the method to generate the key from.
-
MethodKey
MethodKey(java.lang.String aMethod, java.lang.Class<?>[] args)
Creates a key from a method name and a set of parameters.- Parameters:
aMethod
- the method to generate the key from, class name for constructorsargs
- the intended method parameters
-
MethodKey
public MethodKey(java.lang.String aMethod, java.lang.Object[] args)
Creates a key from a method name and a set of arguments.- Parameters:
aMethod
- the method to generate the key fromargs
- the intended method arguments
-
-
Method Detail
-
ambiguousException
private static <T extends java.lang.reflect.Executable> MethodKey.AmbiguousException ambiguousException(java.lang.Class<?>[] classes, java.lang.Iterable<T> applicables)
Creates an ambiguous exception.This method computes the severity of the ambiguity. The only non-severe case is when there is at least one null argument and at most one applicable method or constructor has a corresponding 'Object' parameter. We thus consider that ambiguity is benign in presence of null arguments but severe in the case where the corresponding parameter is of type Object in more than one applicable overloads.
Rephrasing:
- If all arguments are valid instances - no null argument -, ambiguity is severe.
- If there is at least one null argument, the ambiguity is severe if more than one method has a corresponding parameter of class 'Object'.
- Parameters:
classes
- the argument argsapplicables
- the list of applicable methods or constructors- Returns:
- an ambiguous exception
-
asArray
private static java.lang.Class<?>[] asArray(java.lang.Class<?>... args)
Helper to build class arrays.- Parameters:
args
- the classes- Returns:
- the array
-
getApplicables
private static <T extends java.lang.reflect.Executable> java.util.Deque<T> getApplicables(T[] methods, java.lang.Class<?>[] classes)
Returns all methods that are applicable to actual argument types.- Parameters:
methods
- list of all candidate methodsclasses
- the actual types of the arguments- Returns:
- a list that contains only applicable methods (number of formal and actual arguments matches, and argument types are assignable to formal types through a method invocation conversion).
-
isApplicable
private static <T extends java.lang.reflect.Executable> boolean isApplicable(T method, java.lang.Class<?>[] actuals)
Returns true if the supplied method is applicable to actual argument types.- Parameters:
method
- method that will be calledactuals
- arguments signature for method- Returns:
- true if method is applicable to arguments
-
isConvertible
private static boolean isConvertible(java.lang.Class<?> formal, java.lang.Class<?> actual, boolean possibleVarArg)
- Parameters:
formal
- the formal parameter type to which the actual parameter type should be convertibleactual
- the actual parameter type.possibleVarArg
- whether we're dealing with the last parameter in the method declaration- Returns:
- see isMethodInvocationConvertible.
- See Also:
isInvocationConvertible(Class, Class, boolean)
-
isInvocationConvertible
public static boolean isInvocationConvertible(java.lang.Class<?> formal, java.lang.Class<?> actual, boolean possibleVarArg)
Determines whether a type represented by a class object is convertible to another type represented by a class object using a method invocation conversion, treating object types of primitive types as if they were primitive types (that is, a Boolean actual parameter type matches boolean primitive formal type). This behavior is because this method is used to determine applicable methods for an actual parameter list, and primitive types are represented by their object duals in reflective method calls.- Parameters:
formal
- the formal parameter type to which the actual parameter type should be convertibleactual
- the actual parameter type.possibleVarArg
- whether we're dealing with the last parameter in the method declaration- Returns:
- true if either formal type is assignable from actual type, or formal is a primitive type and actual is its corresponding object type or an object-type of a primitive type that can be converted to the formal type.
-
isInvocationConvertible
private static boolean isInvocationConvertible(java.lang.Class<?> formal, java.lang.Class<?> type, boolean strict, boolean possibleVarArg)
Determines parameter-argument invocation compatibility.- Parameters:
formal
- the formal parameter typetype
- the argument typestrict
- whether the check is strict or notpossibleVarArg
- whether we're dealing with the last parameter in the method declaration- Returns:
- true if compatible, false otherwise
-
isPrimitive
private static boolean isPrimitive(java.lang.Class<?> c, boolean possibleVarArg)
Checks whether a parameter class is a primitive.- Parameters:
c
- the parameter classpossibleVarArg
- true if this is the last parameter which can be a primitive array (vararg call)- Returns:
- true if primitive, false otherwise
-
isStrictConvertible
private static boolean isStrictConvertible(java.lang.Class<?> formal, java.lang.Class<?> actual, boolean possibleVarArg)
- Parameters:
formal
- the formal parameter type to which the actual parameter type should be convertibleactual
- the actual parameter type.possibleVarArg
- whether we're dealing with the last parameter in the method declaration- Returns:
- see isStrictMethodInvocationConvertible.
- See Also:
isStrictInvocationConvertible(Class, Class, boolean)
-
isStrictInvocationConvertible
public static boolean isStrictInvocationConvertible(java.lang.Class<?> formal, java.lang.Class<?> actual, boolean possibleVarArg)
Determines whether a type represented by a class object is convertible to another type represented by a class object using a method invocation conversion, without matching object and primitive types. This method is used to determine the more specific type when comparing signatures of methods.- Parameters:
formal
- the formal parameter type to which the actual parameter type should be convertibleactual
- the actual parameter type.possibleVarArg
- whether not we're dealing with the last parameter in the method declaration- Returns:
- true if either formal type is assignable from actual type, or formal and actual are both primitive types and actual can be subject to widening conversion to formal.
-
isVarArgs
public static boolean isVarArgs(java.lang.reflect.Executable method)
Checks whether a method accepts a variable number of arguments.May be due to a subtle bug in some JVMs, if a varargs method is an override, depending on (perhaps) the class introspection order, the isVarargs flag on the method itself will be false. To circumvent the potential problem, fetch the method with the same signature from the super-classes, - which will be different if override -and get the varargs flag from it.
- Parameters:
method
- the method or constructor to check for varargs- Returns:
- true if declared varargs, false otherwise
-
moreSpecific
private static int moreSpecific(java.lang.Class<?>[] a, java.lang.Class<?>[] c1, java.lang.Class<?>[] c2)
Determines which method signature (represented by a class array) is more specific. This defines a partial ordering on the method signatures.- Parameters:
a
- the arguments signaturec1
- first method signature to comparec2
- second method signature to compare- Returns:
- MORE_SPECIFIC if c1 is more specific than c2, LESS_SPECIFIC if c1 is less specific than c2, INCOMPARABLE if they are incomparable.
-
primitiveClass
static java.lang.Class<?> primitiveClass(java.lang.Class<?> parm)
Converts a primitive type to its corresponding class.If the argument type is primitive then we want to convert our primitive type signature to the corresponding Object type so introspection for methods with primitive types will work correctly.
- Parameters:
parm
- a may-be primitive type class- Returns:
- the equivalent object class
-
debugString
public java.lang.String debugString()
Outputs a human-readable debug representation of this key.- Returns:
- method(p0, p1, ...)
-
equals
public boolean equals(java.lang.Object obj)
- Overrides:
equals
in classjava.lang.Object
-
getMethod
java.lang.String getMethod()
Gets this key's method name.- Returns:
- the method name
-
getMostSpecific
private <T extends java.lang.reflect.Executable> T getMostSpecific(T[] methods)
Gets the most specific method that is applicable to actual argument types.Attempts to find the most specific applicable method using the algorithm described in the JLS section 15.12.2 (with the exception that it can't distinguish a primitive type argument from an object type argument, since in reflection primitive type arguments are represented by their object counterparts, so for an argument of type (say) java.lang.Integer, it will not be able to decide between a method that takes int and a method that takes java.lang.Integer as a parameter.
This turns out to be a relatively rare case where this is needed - however, functionality like this is needed.
- Parameters:
methods
- a list of methods- Returns:
- the most specific method.
- Throws:
MethodKey.AmbiguousException
- if there is more than one.
-
getMostSpecificConstructor
public java.lang.reflect.Constructor<?> getMostSpecificConstructor(java.lang.reflect.Constructor<?>[] methods)
Gets the most specific constructor that is applicable to the parameters of this key.- Parameters:
methods
- a list of constructors.- Returns:
- the most specific constructor.
- Throws:
MethodKey.AmbiguousException
- if there is more than one.
-
getMostSpecificMethod
public java.lang.reflect.Method getMostSpecificMethod(java.lang.reflect.Method[] methods)
Gets the most specific method that is applicable to the parameters of this key.- Parameters:
methods
- a list of methods.- Returns:
- the most specific method.
- Throws:
MethodKey.AmbiguousException
- if there is more than one.
-
getParameters
java.lang.Class<?>[] getParameters()
Gets this key's method parameter classes.- Returns:
- the parameters
-
hashCode
public int hashCode()
- Overrides:
hashCode
in classjava.lang.Object
-
toString
public java.lang.String toString()
- Overrides:
toString
in classjava.lang.Object
-
-