我遇到了一种有些奇怪的行为。我使用注释来标记具有特定目的的某些类,然后我使用org.reflections库来查找具有特定注释的所有类。但是,当一个类实现一个返回lambda函数的方法时,反射将不再找到带注释的类。班级的签名没有变化。
注释示例:
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String someValue();
}
使用注释(编辑 - 添加了BaseClass):
public class BaseClass {
public Consumer<Integer> doSomething(){ return null;}
}
@MyAnnotation(someValue = "a")
public class FooBar extends BaseClass {
@Override
public Consumer<Integer> doSomething() {
return null;
}
}
@MyAnnotation(someValue = "bazbar")
public class BarClass extends BaseClass {
@Override
public Consumer<Integer> doSomething(){
return (x) -> {};
}
}
查找注释
private static final Reflections reflections = new Reflections("com.mypackage");
Set<Class<?>> clazzes = reflections.getTypesAnnotatedWith(MyAnnotation.class);
现在 - 设置'clazzes'只包含 1单个类,即FooBar类。如果我从BazBar类中删除lambda返回值也会显示,但只要该类中的一个方法返回一个lambda,反射就不会起作用。
我迷路了,有什么想法吗?
答案 0 :(得分:2)
从issues list看来,这个库似乎还不适合Java 8的功能。我认为你最好的办法是报告这个问题并提供修复。
答案 1 :(得分:1)
您可以在没有任何第三方代码的情况下执行查找,如下所示:
private static <T extends Annotation> Set<Class<?>> getAnnotated(
Class<?> context, Class<T> anno) throws IOException, URISyntaxException {
URI clURI = context.getResource(context.getSimpleName()+".class").toURI();
if(!clURI.getScheme().equals("file")) try {
FileSystems.getFileSystem(clURI);
} catch(FileSystemNotFoundException ex) {
FileSystems.newFileSystem(clURI, Collections.emptyMap());
}
String pkg=context.getPackage().getName();
return Files.list(Paths.get(clURI).getParent())
.map(p->p.getFileName().toString())
.filter(s->s.endsWith(".class"))
.map(s->s.substring(0, s.length()-6))
.map(s-> { try {
return context.getClassLoader().loadClass(pkg+'.'+s);
} catch(ClassNotFoundException ex) { return null; } })
.filter(c -> c!=null && c.isAnnotationPresent(anno))
.collect(Collectors.toSet());
}
Path
优于旧File
的优势在于它对文件系统(存储)进行抽象,因此即使Class
存储在一个文件系统中,也可用于列出包成员jar文件(或存在FileSystemProvider
的任何其他类存储)。
您可以将其用作
Set<Class<?>> clazzes = getAnnotated(context, MyAnnotation.class);
其中context
是您要获取带注释类的包中的Class
。