Java元编程难题:获取所有本身由给定注释a注释的注释

Java元编程难题:获取所有本身由给定注释a注释的注释,java,metaprogramming,puzzle,annotations,Java,Metaprogramming,Puzzle,Annotations,您认为自己是java向导吗? public @interface @a {} public @interface @b {} @Mark public @interface @c {} @Mark public @interface @d {} public @interface @e {} public Class C { @a @b @c @d @e public void x(); } public class Solver { public Annotatio

您认为自己是java向导吗?

public @interface @a {}
public @interface @b {}
@Mark public @interface @c {}    
@Mark public @interface @d {}
public @interface @e {}

public Class C
{
    @a @b @c @d @e public void x();
}

public class Solver
{
    public Annotation[] solve(Method m, Class c);
}
您是否精通反射API的秘密?

public @interface @a {}
public @interface @b {}
@Mark public @interface @c {}    
@Mark public @interface @d {}
public @interface @e {}

public Class C
{
    @a @b @c @d @e public void x();
}

public class Solver
{
    public Annotation[] solve(Method m, Class c);
}
您必须编写方法solve,这样,如果在方法C.x()和Mark.class上调用它,它将返回{C,d}


(这不是家庭作业,是我试图开发的框架元编程框架的真正编程任务)

事实上,我不明白这有多么棘手

更新时,忘记包含contains函数,并且将Annotation.getClass()与Annotation.annotationType()切换时出错。此代码有效

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Mark
public @interface A {}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface B {}

@Retention(RetentionPolicy.RUNTIME)
@Target(value = ElementType.TYPE)
public @interface Mark {}

public class C {
@A @B public void f() {}
}

public class Solver {
public static boolean  contains(Annotation a, Class<?> targetAnnotation) {
    Class<?> c = a.annotationType();
    Annotation[] cas = c.getAnnotations();
    for (Annotation aa : cas) {
        if (aa.annotationType().equals(targetAnnotation)) {
            return true;
        }
    }
    return false;
}

public static Annotation[] getMarked(Method m) {
    List<Annotation> retVal = new ArrayList<Annotation>();
    for (Annotation a : m.getAnnotations()) {
        if (contains(a.getClass().getAnnotations(), Mark.class) {
            retVal.add(a);
        }
    }
    return retVal.toArray(new Annotation[]{});
}

public static void main(String[] args) throws SecurityException, NoSuchMethodException {
    Annotation[] result = getMarked(C.class.getMethod("f"));    
}
} // solver
@Retention(RetentionPolicy.RUNTIME)
@目标({ElementType.METHOD})
@标记
公共@接口A{}
@保留(RetentionPolicy.RUNTIME)
@目标({ElementType.METHOD})
public@interface B{}
@保留(RetentionPolicy.RUNTIME)
@目标(值=ElementType.TYPE)
公共@接口标记{}
公共C类{
@A@B public void f(){}
}
公共类求解器{
公共静态布尔包含(注释a,类targetAnnotation){
类别c=a.annotationType();
注释[]cas=c.getAnnotations();
对于(注释aa:cas){
if(aa.annotationType().equals(targetAnnotation)){
返回true;
}
}
返回false;
}
公共静态注释[]已标记(方法m){
List retVal=new ArrayList();
对于(注释a:m.getAnnotations()){
if(包含(a.getClass().getAnnotations(),Mark.class){
回复。添加(a);
}
}
返回retVal.toArray(新注释[]{});
}
公共静态void main(字符串[]args)引发SecurityException、NoSuchMethodException{
注释[]结果=getMarked(C.class.getMethod(“f”);
}
}//解算器

请注意,这要求所有注释都标记为运行时级别保留,并且返回注释[]可能不是您想要的。您可能希望返回一个包含实际类型的类[](在我的示例中为a.Class)

这是经过测试的。这确实比应该的更难

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface a{}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface b{}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
public @interface Mark{}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Mark
public @interface c{}

public static class D {
    @a @b @c
    public void x() {}
}

public static void main(String[] args) throws Exception {
    Method m = D.class.getMethod("x");

    Collection<Annotation> ret = new HashSet<Annotation>();
    Annotation[] annotations = m.getAnnotations();
    for (Annotation annotation : annotations) {
        Annotation subAnnots = annotation.annotationType().getAnnotation(Mark.class);
        if (subAnnots != null) {
            ret.add(annotation);
        }
    }
    System.out.println(ret);
}
@Retention(RetentionPolicy.RUNTIME)
@目标(ElementType.METHOD)
公共@接口a{}
@保留(RetentionPolicy.RUNTIME)
@目标(ElementType.METHOD)
public@interface b{}
@保留(RetentionPolicy.RUNTIME)
@目标({ElementType.TYPE,ElementType.ANNOTATION\u TYPE})
公共@接口标记{}
@保留(RetentionPolicy.RUNTIME)
@目标(ElementType.METHOD)
@标记
public@interface c{}
公共静态D类{
@a@b@c
公共void x(){}
}
公共静态void main(字符串[]args)引发异常{
方法m=D.class.getMethod(“x”);
Collection ret=new HashSet();
Annotation[]annotations=m.getAnnotations();
用于(注释:注释){
Annotation subAnnots=Annotation.annotationType().getAnnotation(Mark.class);
if(子注释!=null){
ret.add(注释);
}
}
系统输出打印项次(ret);
}

我想这就引出了一个问题:为什么annotationType()有效,而getClass()无效。

你认为我会因为你暗示我(不是)而为你的作业编写代码而绊倒吗一个向导?还有,Meta就是谋杀:我是一个java向导,这对我来说太琐碎了,所以我只是用向导的方式嘲笑你。唯一令人困惑的是,为什么你认为这是一个难题。你尝试了什么?发生了什么事?默认的保留策略是什么?你在注释上指定了RetentionPolicy.RUNTIME吗?否则-它们在运行时被擦除。他是对的,我的原始代码不起作用,因为我使用的是Annotation.getClass(),我应该使用Annotation.annotationType()。在处理反射时很容易被缠绕在轴上。Annotation.getClass()将返回类,而不是它所表示的注释的类。元编程有时很难看!具体来说,注释对象是特定于要注释的单个类的代理对象。因为它是元对象,所以getClass()是注释实例的类,而annotationType()是getClass()的元等价物谢谢杰里科,这很有道理。