Details
-
Bug
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
3.12.0
-
None
Description
Summary
MethodUtils.getMatchingMethod() fails with "Found multiple candidates for method" message if the method is an override of an abstract method and parameter types do not exactly match the declared types.
Reproducer
public class App { static abstract class Base { abstract void handle(Exception e); } static class BaseImpl extends Base { @Override void handle(Exception e) { e.printStackTrace(); } } public static void main(String[] args) { MethodUtils.getMatchingMethod(BaseImpl.class, "handle", RuntimeException.class); } }
When the the program is executed, you would observe the following exception:
Exception in thread "main" java.lang.IllegalStateException: Found multiple candidates for method handle(class java.lang.RuntimeException) on class dev.pshevche.App$BaseImpl : [void dev.pshevche.App$BaseImpl.handle(java.lang.Exception),abstract void dev.pshevche.App$Base.handle(java.lang.Exception)] at org.apache.commons.lang3.reflect.MethodUtils.getMatchingMethod(MethodUtils.java:784) at dev.pshevche.App.main(App.java:22)
The behavior of this method has changed between versions 3.11 and 3.12.0. Previously, the method would pick the first method that matches the signature and replace it only if a method with a more specific signature is found. The methods would also be ordered according to the class hierarchy: https://github.com/apache/commons-lang/blob/rel/commons-lang-3.11/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java#L760. Starting with 3.12.0, all the methods would have an equal distance and the method will throw the above exception: https://github.com/apache/commons-lang/blob/master/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java#L758
I'd argue that overridden methods are more specific and have a smaller distance than those of the parent and should be preferred. But if it is by design, could you provide some guidance on how to work around this? Currently, we can't provide any parameter to change the behavior or fetch all matching methods and filter out abstract methods.