code: public static Object invokeMethod(Object object, String methodName, Object[] args, Class<?>[] paramTypes)
              throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
          if (args == null) {
              args = EMPTY_OBJECT_ARRAY;
          }
          if (paramTypes == null) {
              paramTypes = EMPTY_CLASS_PARAMETERS;
          }
          Method method = getMatchingAccessibleMethod(object.getClass(), methodName, args, paramTypes);
          if (method == null) {
              throw new NoSuchMethodException("No such accessible method: " + methodName + "() on object: " + object.getClass().getName());
          }
          return invokeMethod(object, method, args, paramTypes);
      }
docs: <p>Invoke a named method whose parameter type matches the object type.</p>
  
  <p>The behaviour of this method is less deterministic
  than {@link
  #invokeExactMethod(Object object,String methodName,Object[] args,Class[] paramTypes)}.
  It loops through all methods with names that match
  and then executes the first it finds with compatible parameters.</p>
  
  <p>This method supports calls to methods taking primitive parameters
  via passing in wrapping classes. So, for example, a {@code Boolean} class
  would match a {@code boolean} primitive.</p>
  
  @param object invoke method on this object
  @param methodName get method with this name
  @param args use these arguments - treat null as empty array
  @param paramTypes match these parameters - treat null as empty array
  @return the value returned by the invoked method
  @throws NoSuchMethodException if there is no such accessible method
  @throws InvocationTargetException wraps an exception thrown by the method invoked
  @throws IllegalAccessException if the requested method is not accessible via reflection