Java metaprogramming puzzle: get all annotations that are annotated themselves with this annotation A

Do you think you are a java master?

What are you good at secrets of the reflection 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); } 

You need to write a solution method, so if it is called in the Cx () method and Mark.class, it returns {c, d}.

(This is not homework, this is real programming for the metaprogramming framework I am trying to develop)

+4
source share
2 answers

It is tested to work. It was really harder than it should have been.

 @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); } 

I think it just asks a question about why annotationType () works, but getClass () does not.

+6
source

In fact, I do not understand how difficult it is.

Update, forgot to include the contains function, and also made a mistake when switching Annotation.getClass () with Annotation.annotationType (). This code works

 @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 

Note that this requires that all annotations be noted while maintaining a run-time level, and that returning Annotation [] is probably not what you want. You probably want to return a class [] full of actual types (in my example, A.class)

+1
source

All Articles