未选中的强制转换:由类包装的通配符转换为由类包裹的另一种类型



我正试图通过带有反射的Annotation标准收集类集(为了提高性能(:

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

问题是我得到的是Set<Class<?>>而不是Set<Class<Foo>>。通过使用.filter(Foo.class::isAssignableFrom)筛选集合,我成功地检查了类是否是Foo的类型。在这一点上,我知道我使用的是Foo类型的类。不幸的是,当从Class<?>转换为Class<Foo>时,我得到了未选中的转换,我希望避免这种情况。

以下是完整的代码块:

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());

对此有什么建议吗?

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

其次,您需要获得类型为Class<?>Class<? extends Foo>uncheckedFoo。如果您不想使用未检查的强制转换,可以使用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());

您可以使用一个好的旧循环而不是流,以便在强制转换时向编译器明确每个项都是assignableFromFoo。否则,它在下一步中忘记所有项目都是Foo类型。

铸件检查和铸造必须在一个步骤中

Set<Class<Foo>> foos = new HashSet<>();
for(Class<?> i : reflections.getTypesAnnotatedWith(
BooAnnotation.class ) )
{
if(Foo.class.isAssignableFrom(i))
{
foos.add(Foo.class.cast(i)); //cast from Foo.class
}
}

注意:您可以使用forEach而不是for(:)循环

最新更新