首页 > 解决方案 > 未经检查的强制转换:由 Class 包装的通配符到由 Class 包装的另一种类型

问题描述

我正在尝试通过带有反射的注释标准收集一组类(为了提高性能):

Reflections reflections = new Reflections(packagePrefix);
Set<Class<Foo>> foos = reflections.getTypesAnnotatedWith(BooAnnotation.class);

问题是我得到Set<Class<?>>的不是Set<Class<Foo>>. Foo我设法通过过滤集合来检查类是否是.filter(Foo.class::isAssignableFrom). 在这一点上,我知道我正在使用类型为 的类Foo。不幸的是,当我从Class<?>to转换时,Class<Foo>我得到了Unchecked cast,我想避免这种情况。

这是完整的代码块:

Reflections reflections = new Reflections(packagePrefix);
Set<Class<Foo>> foos = reflections.getTypesAnnotatedWith(BooAnnotation.class)
        .stream()
        .filter(Foo.class::isAssignableFrom)
        .map(uncheckedFoo -> {
          @SuppressWarnings("unchecked")
          Class<Foo> foo = (Class<Foo>) uncheckedFoo;
          return foo;
        })
        .collect(Collectors.toSet());

对此有何建议?

标签: javagenericscasting

解决方案


首先,Class<Foo>是针对完全表示类的类对象Foo,而不是其他类。只能有一个类型的对象Class<Foo>。因此,拥有Set其中一个是没有意义的。似乎您正在收集Set代表Foo及其子类的类对象。在这种情况下,它应该是Set<Class<? extends Foo>>

其次,您需要获取uncheckedFoo类型Class<?>Class<? extends Foo>. 如果您不想使用未经检查的强制转换,您可以使用Class::asSubclass(). 因此,您可以执行以下操作:

Set<Class<? extends Foo>> foos = reflections.getTypesAnnotatedWith(BooAnnotation.class)
        .stream()
        .filter(Foo.class::isAssignableFrom)
        .map(uncheckedFoo -> uncheckedFoo.asSubclass(Foo.class))
        .collect(Collectors.toSet());

推荐阅读