Java 中的泛型,返回一组泛型类 Set<T>



所以我有这个代码,我试图返回一组正在扩展另一个类的类

public static <T> Set<T> getClassesExtending(Class<T> clazz) {
Reflections reflections = new Reflections("");
Set<Class<? extends T>> classes = reflections.getSubTypesOf(clazz);
if (classes.size() <= 0) return new HashSet<>();
Set<T> extending = classes.stream().filter(c -> c instanceof T).collect(Collectors.toSet());
return extending;
}

问题:

c instanceof T //shows compile error 'Class or array expected' above 'T'

例如,如果我要写。。。

getClassesExtending(MyClass.class).forEach(c -> c.methodInMyClass())

它会起作用的。有什么建议吗?

  • 首先,根据您所描述的使用方式,您需要
    • 查找扩展类clazz的类
    • 使用它们的默认构造函数创建它们的对象,然后
    • 调用它们上的方法

这个代码应该可以完成你的工作

public static <T> Set<? extends T> getClassesExtending(Class<T> clazz) {
Reflections reflections = new Reflections("");
Set<Class<? extends T>> classes = reflections.getSubTypesOf(clazz);
if (classes.size() <= 0) return new HashSet<>();
Set<? extends T> extending =
classes.stream().map(aClass -> {
try {
return aClass.getConstructor().newInstance();
} catch (Exception e) {
return null;
}
}).collect(Collectors.toSet());
return extending;
}    

我建议您引入一个filter()操作来过滤掉任何没有无arg构造函数的子类,以防止extending集中出现null

  • 其次,当你做这个时

    Set<T> extending = classes.stream().filter(c -> c instanceof T).collect(Collectors.toSet());

如果你真的试图将集合过滤成类,那么这个操作将是幂等的,也就是说,它不会在集合中产生任何变化。

最后,c instanceof T导致编译错误的原因是,instanceOf运算符不允许在其rhs上使用不可重写类型,并且泛型类型是不可重写的。(JLS 11节:15.20.2(

这里的问题是T在运行时被擦除。

你可以试试这个:

Set<T> extending = classes.stream().filter(c -> c.isAssignableFrom(clazz)).collect(Collectors.toSet());

最新更新