in src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java [723:770]
public static Method getMatchingMethod(final Class<?> cls, final String methodName,
final Class<?>... parameterTypes) {
Objects.requireNonNull(cls, "cls");
Validate.notEmpty(methodName, "methodName");
final List<Method> methods = Stream.of(cls.getDeclaredMethods())
.filter(method -> method.getName().equals(methodName))
.collect(Collectors.toList());
ClassUtils.getAllSuperclasses(cls).stream()
.map(Class::getDeclaredMethods)
.flatMap(Stream::of)
.filter(method -> method.getName().equals(methodName))
.forEach(methods::add);
for (final Method method : methods) {
if (Arrays.deepEquals(method.getParameterTypes(), parameterTypes)) {
return method;
}
}
final TreeMap<Integer, List<Method>> candidates = new TreeMap<>();
methods.stream()
.filter(method -> ClassUtils.isAssignable(parameterTypes, method.getParameterTypes(), true))
.forEach(method -> {
final int distance = distance(parameterTypes, method.getParameterTypes());
final List<Method> candidatesAtDistance = candidates.computeIfAbsent(distance, k -> new ArrayList<>());
candidatesAtDistance.add(method);
});
if (candidates.isEmpty()) {
return null;
}
final List<Method> bestCandidates = candidates.values().iterator().next();
if (bestCandidates.size() == 1 || !Objects.equals(bestCandidates.get(0).getDeclaringClass(),
bestCandidates.get(1).getDeclaringClass())) {
return bestCandidates.get(0);
}
throw new IllegalStateException(
String.format("Found multiple candidates for method %s on class %s : %s",
methodName + Stream.of(parameterTypes).map(String::valueOf).collect(Collectors.joining(",", "(", ")")),
cls.getName(),
bestCandidates.stream().map(Method::toString).collect(Collectors.joining(",", "[", "]")))
);
}