There is a simple solution, but that simplicity comes at the cost of performance.
I'm using this monster instead:
public static Method findMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException {
// First try the trivial approach. This works usually, but not always.
try {
return clazz.getMethod(methodName, parameterTypes);
} catch (NoSuchMethodException ex) {
}
// Then loop through all available methods, checking them one by one.
for (Method method : clazz.getMethods()) {
String name = method.getName();
if (!methodName.equals(name)) { // The method must have right name.
continue;
}
Class<?>[] acceptedParameterTypes = method.getParameterTypes();
if (acceptedParameterTypes.length != parameterTypes.length) { // Must have right number of parameters.
continue;
}
boolean match = true;
for (int i = 0; i < acceptedParameterTypes.length; i++) { // All parameters must be right type.
if (null != parameterTypes[i] && !acceptedParameterTypes[i].isAssignableFrom(parameterTypes[i])) {
match = false;
break;
}
if (null == parameterTypes[i] && acceptedParameterTypes[i].isPrimitive()) { // Accept null except for primitive fields.
match = false;
break;
}
}
if (match) {
return method;
}
}
// None of our trials was successful!
throw new NoSuchMethodException();
}
parameterTypes
are what you get from your value.getClass()
. Some or all of them can be also null. Then they are treated as matces for any non-primitive parameter fields.
Even this isn't quit perfect: If there are several methods that are polymorphically suitable but none of which matches exactly, then the returned method is chosen arbitrarily (the first match in the array that clazz.getMethods()
returns is taken). This behavior differs from Java the Language behavior, in which the "closest match" is always used.
If getting the method by name is sufficient (i.e. you assume that the parameters are suitable if the name matches), then you can manage with much simpler (and somewhat faster):
public static Method findMethod(Class<?> clazz, String methodName) {
for (Method method : clazz.getMethods()) {
if (method.getName().equals(methodName)) {
return method;
}
}
throw new NoSuchMethodException();
}
To further boost it up, consider some sort of cache.