code: public static List<Method> getCommandMethods(Class<?> cls, String methodName) {
          Set<Method> candidates = new HashSet<Method>();
          // traverse public member methods (excludes static/non-public, includes inherited)
          candidates.addAll(Arrays.asList(Assert.notNull(cls, "class").getMethods()));
          // traverse directly declared methods (includes static/non-public, excludes inherited)
          candidates.addAll(Arrays.asList(Assert.notNull(cls, "class").getDeclaredMethods()));
  
          List<Method> result = new ArrayList<Method>();
          for (Method method : candidates) {
              if (method.isAnnotationPresent(Command.class)) {
                  if (methodName == null || methodName.equals(method.getName())) { result.add(method); }
              }
          }
          Collections.sort(result, new Comparator<Method>() {
              public int compare(Method o1, Method o2) { return o1.getName().compareTo(o2.getName()); }
          });
          return result;
      }
docs: Helper to get methods of a class annotated with {@link Command @Command} via reflection, optionally filtered by method name (not {@link Command#name() @Command.name}).
  Methods have to be either public (inherited) members or be declared by {@code cls}, that is "inherited" static or protected methods will not be picked up.
  
  @param cls the class to search for methods annotated with {@code @Command}
  @param methodName if not {@code null}, return only methods whose method name (not {@link Command#name() @Command.name}) equals this string. Ignored if {@code null}.
  @return the matching command methods, or an empty list
  @see #invoke(String, Class, String...)
  @since 3.6.0