为什么当类返回 Lambda 时反射不起作用 [英] Why doesn't reflection work when a class returns Lambdas

查看:33
本文介绍了为什么当类返回 Lambda 时反射不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个有点奇怪的行为.我使用注释来标记具有特定用途的某些类,然后我使用 org.reflections 库来查找具有特定注释的所有类.然而,当一个类实现一个返回 lambda 函数的方法时,反射将不再找到带注释的类.类的签名不变.

I have encountered a somewhat strange behaviour. I use annotations to mark certain classes with a particular purpose, and then I use org.reflections library to find all the classes with the particular annotation. However when a class implements a method that returns a lambda function, the reflection won't find the annotated class anymore. The signature of the class is unchanged.

注解示例:

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
   String someValue();
}

使用注释(编辑 - 添加了 BaseClass):

Using the annotation (EDIT - added the 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,反射将不起作用.

Now - the set 'clazzes' only contains 1 single class, the FooBar class. If I remove the lambda return value from the BazBar class that one too shows up, but as soon as one method in the class returns a lambda the reflection wont work.

我迷路了,有什么想法吗?

I'm lost, any ideas?

推荐答案

您可以在没有任何第三方代码的情况下执行查找,如下所示:

You may perform the lookup without any third-party code as follows:

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 的优点在于它抽象了文件系统(存储),因此即使 存储在 jar 文件中(或任何其他类型的类存储,其中存在 FileSystemProvider).

The advantage of Path over good old File is that it abstracts over the filesystem (storage) and thus can be used to list package members even if the Class is stored in a jar file (or any other kind of class storage for which a FileSystemProvider exists).

您可以将其用作

Set<Class<?>> clazzes  = getAnnotated(context, MyAnnotation.class);

其中 context 是包中的一个 Class,您要为其获取带注释的类.

where context is a Class within the package for which you want to get a annotated classes.

这篇关于为什么当类返回 Lambda 时反射不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆