Uploaded image for project: 'Commons Lang'
  1. Commons Lang
  2. LANG-1694

`MethodUtils.getMatchingMethod` fails with "Found multiple candidates" when the method is abstract

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Major
    • Resolution: Fixed
    • 3.12.0
    • 3.13.0
    • lang.reflect.*
    • 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.

       

      Attachments

        Activity

          People

            Unassigned Unassigned
            pshevche Pavlo Shevchenko
            Votes:
            2 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: