我有一个项目,其中服务接口使用@Service
注释(自定义注释,而不是Spring)进行注释,并且每个服务可以有多个实现(hibernate,mongodb等)。
我正在尝试使用这样的反射来加载实现类:
步骤1:使用@Service
注释加载所有接口
步骤2:加载每个接口的所有子类
以下是代码:
public static void main(String[] args) throws Exception{
Reflections reflections = new Reflections("net.jitix.cfs");
//load annotated interfaces
Set<Class<?>> types=reflections.getTypesAnnotatedWith(Service.class);
Iterator<Class<?>> typeIterator=types.iterator();
typeIterator.forEachRemaining(new Consumer<Class<?>>() {
@Override
public void accept(Class<?> type) {
if(!type.isInterface()){
typeIterator.remove();
}
}
});
for(Class<?> type:types){
//load implementation classes
Set<Class<?>> implTypes=reflections.getSubTypesOf(type); //error here
}
//rest of the code
}
我得到的编译错误:Type mismatch: cannot convert from Set<Class<? extends capture#8-of ?>> to Set<Class<?>>
根据我的understanding Class<?>
表示该类型可以是任何内容,因此我很困惑为什么需要Class<T>
的方法无法将Class<?>
作为参数。
有谁能帮助我理解为什么会这样?我的方法有可能的替代方案吗?提前谢谢!
编辑:根据@MGorgon的评论和@StriplingWarrior以及@Sotirios Delimanolis使用反射法的答案是不可能的。有没有什么办法可以获得类型为Class<?>
答案 0 :(得分:2)
这个问题的症结与反思无关,而是与协方差/逆差相关。它有效:
为什么我无法将
Set<? extends Something>
分配给Set<?>
?
答案是,如果你有一个Set<?>
,那么编译器会允许你向该集添加任何类型的对象(比如说X
),并且有人试图从如果原来的Set<? extends Something>
未延伸 X
,原始Something
会收到运行时错误。
这个原则可以更简单地证明:
Set<Dog> dogs = getDogs();
Set<Pet> pets = dogs; // the compiler will complain here
pets.add(new Cat("Fluffy")); // to avoid letting this happen
for(Dog dog : dogs) // which would cause an exception here
{
...
}
因为你(大概)知道你并不打算在这个集合中添加任何东西,所以告诉编译器你知道你通过一点点明确做了什么可能是安全的铸造:
Set<Class<?>> implTypes= (Set<Class<?>>)(Set<?>)reflections.getSubTypesOf(type);
答案 1 :(得分:1)
getSubTypesOf
方法声明为
public <T> Set<Class<? extends T>> getSubTypesOf(final Class<T> type) {
这是一种通用方法,将T
声明为类型参数。调用方法时,方法调用会隐式或因为显式提供类型参数。
您使用Class<?>
类型的参数调用了该方法。该方法将捕获?
类型。因此,方法返回类型将变为Set<Class<? extends CAP of ?>>
,即。一组某种未知类型的类,它是某种特定未知类型的子类型。
但是,您尝试将其分配给Set<Class<?>>
,这是一组未知类型的类。但是这种未知类型不一定是某种特定未知类型的子类型。我知道当你大声说出来时没有多大意义,但请考虑?
或CAP of ?
作为特定类型。这与尝试
Set<Class<?>> implTypes = new HashSet<Class<Integer>>();
由于Class
为final
,因此无法立即显示,因此无法将HashSet<Class<Integer>>
分配给Set<Class<?>>
,与ArrayList<ArrayList<Integer>
不同{1}}无法分配给List<List<?>>
。
补充阅读: