在泛型的情况下,lambda中的返回类型错误

时间:2017-11-24 10:55:02

标签: java generics lambda compiler-errors java-8

拥有此通用代码

static final <T> List<Class<? extends T>> findSubClasses(Class<T> clz, String packageName){
    ClassPathScanningCandidateComponentProvider provider =
                new ClassPathScanningCandidateComponentProvider(false);
    provider.addIncludeFilter(new AssignableTypeFilter(clz));
    Set<BeanDefinition> beanDefinitions = provider.findCandidateComponents(packageName);
    List<Class<? extends T>> subClasses = beanDefinitions.stream().map(b->mapToClass(b, clz)).collect(Collectors.toList());
        return subClasses;
}

private static final <T> Class<? extends T> mapToClass(BeanDefinition beanDefinition, Class<T> clz) {
   String className = beanDefinition.getBeanClassName();
   try {
       return (Class<? extends T>) Class.forName(className);
   } catch (ClassNotFoundException e) {
       log.error("Failed to load the scanned class {}", className, e);
   }
   return null;
}

我在b->mapToClass(b, clz)

上有此错误消息
Bad return type in lambda expression: Class<capture of ? extends T> cannot be converted to Class<Object>

如何解决这个问题?

2 个答案:

答案 0 :(得分:4)

这是编译器 IntelliJ无法正确推断map()操作的返回类型的情况。

您可以通过简单地提供新的流项目类型来帮助它:Class<? extends T>,如下所示:

List<Class<? extends T>> subClasses = beanDefinitions.stream()
        .<Class<? extends T>>map(b-> mapToClass(b, clz))
        .collect(Collectors.toList());

请注意,它似乎只是IntelliJ中的一个错误,因为javac似乎很乐意编译它(正如预期的那样)。

作为副节点,您可以通过以下方式避免mapToClass()中未经检查的强制转换:

return Class.forName(className).asSubclass(clz);

答案 1 :(得分:0)

您提供给这些方法的通用信息是不相关的,即使您为它们指定了相同的名称(T)。如果你想让它们以某种方式相关,你需要在类级别声明它们。

但在这种情况下它不起作用,因为你的方法是static;因此,这将起作用:

 public class YourClass<T> {

    final List<Class<? extends T>> findSubClasses(Class<T> clz, String packageName) {
        ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
        provider.addIncludeFilter(new AssignableTypeFilter(clz));
        Set<BeanDefinition> beanDefinitions = provider.findCandidateComponents(packageName);
        List<Class<? extends T>> subClasses = beanDefinitions.stream().map(b -> mapToClass(b, clz))
                .collect(Collectors.toList());
        return subClasses;
    }

    private final Class<? extends T> mapToClass(BeanDefinition beanDefinition, Class<T> clz) {
        String className = beanDefinition.getBeanClassName();
        try {
            return (Class<? extends T>) Class.forName(className);
        } catch (ClassNotFoundException e) {

        }
        return null;
    }
}

修改

确实Didier's points out这与javac-8javac-9一样正常,因此根本不需要进行任何重构......