Class MethodKey
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 ClassesModifier and TypeClassDescriptionstatic class
Simple distinguishable exception, used when we run across ambiguous overloading. -
Field Summary
FieldsModifier and TypeFieldDescriptionMaps from primitive types to invocation compatible classes.private static final int
The hash code constants.private final int
The hash code.private static final int
A method/ctor doesn't match a previously compared one.private static final int
whether a method/ctor is less specific than a previously compared one.private final String
The method name.private static final int
whether a method/ctor is more specific than a previously compared one.private static final Class<?>[]
A marker for empty parameter list.private final Class<?>[]
The parameters.private static final int
The initial size of the primitive conversion map.Maps from primitive types to invocation compatible primitive types. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprivate static <T extends Executable>
MethodKey.AmbiguousExceptionambiguousException
(Class<?>[] classes, Iterable<T> applicables) Creates an ambiguous exception.private static Class<?>[]
Helper to build class arrays.Outputs a human-readable debug representation of this key.boolean
private static <T extends Executable>
Deque<T>getApplicables
(T[] methods, Class<?>[] classes) Returns all methods that are applicable to actual argument types.(package private) String
Gets this key's method name.private <T extends Executable>
TgetMostSpecific
(T[] methods) Gets the most specific method that is applicable to actual argument types.Constructor<?>
getMostSpecificConstructor
(Constructor<?>[] methods) Gets the most specific constructor that is applicable to the parameters of this key.getMostSpecificMethod
(Method[] methods) Gets the most specific method that is applicable to the parameters of this key.(package private) Class<?>[]
Gets this key's method parameter classes.int
hashCode()
private static <T extends Executable>
booleanisApplicable
(T method, Class<?>[] actuals) Returns true if the supplied method is applicable to actual argument types.private static boolean
isConvertible
(Class<?> formal, Class<?> actual, boolean possibleVarArg) static boolean
isInvocationConvertible
(Class<?> formal, 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
(Class<?> formal, Class<?> type, boolean strict, boolean possibleVarArg) Determines parameter-argument invocation compatibility.private static boolean
isPrimitive
(Class<?> c, boolean possibleVarArg) Checks whether a parameter class is a primitive.private static boolean
isStrictConvertible
(Class<?> formal, Class<?> actual, boolean possibleVarArg) static boolean
isStrictInvocationConvertible
(Class<?> formal, 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
(Executable method) Checks whether a method accepts a variable number of arguments.private static int
moreSpecific
(Class<?>[] a, Class<?>[] c1, Class<?>[] c2) Determines which method signature (represented by a class array) is more specific.(package private) static Class<?>
primitiveClass
(Class<?> parm) Converts a primitive type to its corresponding class.toString()
-
Field Details
-
PRIMITIVE_SIZE
private static final int PRIMITIVE_SIZEThe initial size of the primitive conversion map.- See Also:
-
hashCode
private final int hashCodeThe hash code. -
method
The method name. -
params
The parameters. -
NOARGS
A marker for empty parameter list. -
HASH
private static final int HASHThe hash code constants.- See Also:
-
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
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_SPECIFICwhether a method/ctor is more specific than a previously compared one.- See Also:
-
LESS_SPECIFIC
private static final int LESS_SPECIFICwhether a method/ctor is less specific than a previously compared one.- See Also:
-
INCOMPARABLE
private static final int INCOMPARABLEA method/ctor doesn't match a previously compared one.- See Also:
-
-
Constructor Details
-
MethodKey
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
-
MethodKey
MethodKey(Executable aMethod) Creates a key from a method.- Parameters:
aMethod
- the method to generate the key from.
-
MethodKey
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
-
-
Method Details
-
getMethod
String getMethod()Gets this key's method name.- Returns:
- the method name
-
getParameters
Class<?>[] getParameters()Gets this key's method parameter classes.- Returns:
- the parameters
-
hashCode
public int hashCode() -
equals
-
toString
-
debugString
Outputs a human-readable debug representation of this key.- Returns:
- method(p0, p1, ...)
-
isVarArgs
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
-
getMostSpecificMethod
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.
-
getMostSpecificConstructor
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.
-
isInvocationConvertible
public static boolean isInvocationConvertible(Class<?> formal, 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.
-
isStrictInvocationConvertible
public static boolean isStrictInvocationConvertible(Class<?> formal, 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.
-
primitiveClass
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
-
asArray
Helper to build class arrays.- Parameters:
args
- the classes- Returns:
- the array
-
isInvocationConvertible
private static boolean isInvocationConvertible(Class<?> formal, 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
-
getMostSpecific
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.
-
ambiguousException
private static <T extends Executable> MethodKey.AmbiguousException ambiguousException(Class<?>[] classes, 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
-
moreSpecific
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.
-
isPrimitive
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
-
getApplicables
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
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
- 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:
-
isStrictConvertible
private static boolean isStrictConvertible(Class<?> formal, 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:
-