java - 如何获取从具有指定泛型的接口(interface)继承的所有类的列表(接口(interface)<具体类>)

标签 java generics interface implementation

我有命令界面

public interface ICommand {...}

以及与特定命令关联的处理程序接口(interface)

public interface ICommandHandler<T extends ICommand> {
   IResponse handle(T command);
}

例如,我有具体的命令

public class GetCatalogById implements ICommand{

    private final long catalogId;

    public GetCatalogById(long catalogId) {
        this.catalogId = catalogId;
    }

    public long getCatalogId() {
        return catalogId;
    }  
}

如何以编程方式获取项目中所有类的列表(List)

implements ICommandHandler<GetCatalogById>

最佳答案

您的问题可以分为 2 个子问题:

  1. 获取实现ICommandHandler的所有类的列表
  2. 过滤具有必需类型参数的内容

@ArvindKumarAvinash也就是说,你可以找到第一个子问题的许多解决方案 here .

这是我的第二个解决方案:

public static <T extends ICommand> List<Class<? extends ICommandHandler<T>>> getCommandHandlers(
        Class<T> commandClass, String packageName
) {
    return new Reflections(packageName).getSubTypesOf(ICommandHandler.class).stream()
            .filter(subtype -> !subtype.isInterface())
            .filter(subtype -> Objects.equals(getParameter(subtype, ICommandHandler.class, 0), commandClass))
            .map(subtype -> (Class<? extends ICommandHandler<T>>) subtype)
            .collect(Collectors.toList());
}


@Nullable
public static <T> Type getParameter(
        Class<T> clazz,
        Class<? super T> parametrizedParent,
        int index
) {
    Type result = null;
    for (ParameterizedType parent : getParameterizedParents(clazz, parametrizedParent)) {
        result = parent.getActualTypeArguments()[index];
        if (!(result instanceof TypeVariable)) return result;
        index = getTypeVariableIndex((TypeVariable<?>) result);
    }
    return result;
}

private static <T> List<ParameterizedType> getParameterizedParents(Class<? extends T> clazz, Class<T> parent) {
    List<ParameterizedType> genericParents = new ArrayList<>();
    Class<? extends T> current = clazz;
    while (true) {
        Type supertype = getSuperType(current, parent);
        if (supertype instanceof ParameterizedType)
            genericParents.add((ParameterizedType) supertype);
        else genericParents.clear();
        Type rawSupertype = toRawType(supertype);
        if (rawSupertype == parent) {
            Collections.reverse(genericParents);
            return genericParents;
        }
        current = (Class<? extends T>) rawSupertype;
    }
}

private static <T> Type getSuperType(Class<? extends T> child, Class<T> parent) {
    if (child == parent) return child;
    Type superclass = child.getGenericSuperclass();
    if (isSubTypeOfClass(superclass, parent)) return superclass;
    for (Type type : child.getGenericInterfaces())
        if (isSubTypeOfClass(type, parent)) return type;
    throw new IllegalArgumentException(child.getName() + " is not assignable from " + parent.getName());
}

private static int getTypeVariableIndex(final TypeVariable<?> typeVariable) {
    return Arrays.asList(typeVariable.getGenericDeclaration().getTypeParameters()).indexOf(typeVariable);
}

private static boolean isSubTypeOfClass(Type type, Class<?> clazz) {
    Type rawType = toRawType(type);
    return rawType instanceof Class && clazz.isAssignableFrom((Class<?>) rawType);
}

private static Type toRawType(Type type) {
    return type instanceof ParameterizedType ? ((ParameterizedType) type).getRawType() : type;
}

关于java - 如何获取从具有指定泛型的接口(interface)继承的所有类的列表(接口(interface)<具体类>),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58548285/

相关文章:

c# - 具有相同功能的 2 个接口(interface)上的最小起订量

json - 如何使用 MarshalJSON 将结构转换为具有自定义字段类型的公共(public)结构

java - 按下一个按钮来保存来自不同 Activity 的地理位置详细信息并将其显示在 MapView 上?

C#:测试一个对象是否实现了接口(interface)列表中的任何一个?

scala - 为什么 traits 不能有带 Context Bounds 的参数

android - 跨多个 fragment 重用回调接口(interface)

java - Java中不使用replace函数替换字符

java - 在 Android 中选择列表项时使列表项在屏幕上居中?

java - 获取错误 : org. openqa.selenium.WebDriverException:未知错误:键应该是一个字符串

c++ - C++异常捕获迟了,这可能是什么原因?