code: public static <T> @Nullable Class<? extends T> find(final @NonNull Class<? extends T> first, final @NonNull Class<T> type, final @NonNull Predicate<Class<? extends T>> predicate) {
      final Deque<Class<? extends T>> classes = new ArrayDeque<>();
      classes.add(first);
  
      while(!classes.isEmpty()) {
        final /* @Nullable */ Class<? extends T> next = classes.remove();
  
        if(predicate.test(next)) {
          return next;
        }
  
        final /* @Nullable */ Class<?> parent = next.getSuperclass();
        if(parent != null && type.isAssignableFrom(parent)) {
          classes.add(parent.asSubclass(type));
        }
  
        for(final /* @NonNull */ Class<?> interfaceType : next.getInterfaces()) {
          if(type.isAssignableFrom(interfaceType)) {
            classes.add(interfaceType.asSubclass(type));
          }
        }
      }
  
      return null;
    }
docs: thanks, kenzie