55

Suppose I have this annotation class


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MethodXY {
    public int x();
    public int y();
}

public class AnnotationTest {
    @MethodXY(x=5, y=5)
    public void myMethodA(){ ... }

    @MethodXY(x=3, y=2)
    public void myMethodB(){ ... }
}

So is there a way to look into an object, "seek" out the method with the @MethodXY annotation, where its element x = 3, y = 2, and invoke it?

Thanks

3 Answers 3

85

Here is a method, which returns methods with specific annotations:

public static List<Method> getMethodsAnnotatedWith(final Class<?> type, final Class<? extends Annotation> annotation) {
    final List<Method> methods = new ArrayList<Method>();
    Class<?> klass = type;
    while (klass != Object.class) { // need to traverse a type hierarchy in order to process methods from super types
        // iterate though the list of methods declared in the class represented by klass variable, and add those annotated with the specified annotation
        for (final Method method : klass.getDeclaredMethods()) {
            if (method.isAnnotationPresent(annotation)) {
                Annotation annotInstance = method.getAnnotation(annotation);
                // TODO process annotInstance
                methods.add(method);
            }
        }
        // move to the upper class in the hierarchy in search for more methods
        klass = klass.getSuperclass();
    }
    return methods;
}

It can be easily modified to your specific needs. Pls note that the provided method traverses class hierarchy in order to find methods with required annotations.

Here is a method for your specific needs:

public static List<Method> getMethodsAnnotatedWithMethodXY(final Class<?> type) {
    final List<Method> methods = new ArrayList<Method>();
    Class<?> klass = type;
    while (klass != Object.class) { // need to iterated thought hierarchy in order to retrieve methods from above the current instance
        // iterate though the list of methods declared in the class represented by klass variable, and add those annotated with the specified annotation
        for (final Method method : klass.getDeclaredMethods()) {
            if (method.isAnnotationPresent(MethodXY.class)) {
                MethodXY annotInstance = method.getAnnotation(MethodXY.class);
                if (annotInstance.x() == 3 && annotInstance.y() == 2) {         
                    methods.add(method);
                }
            }
        }
        // move to the upper class in the hierarchy in search for more methods
        klass = klass.getSuperclass();
    }
    return methods;
}

For invocation of the found method(s) pls refer a tutorial. One of the potential difficulties here is the number of method arguments, which could vary between found methods and thus requiring some additional processing.

Sign up to request clarification or add additional context in comments.

9 Comments

I guess every code sample I have seen so far all involves "scanning" all methods
Just a heads up, annotation might be null in the line Annotation annotInstance = method.getAnnotation(annotation);
@kliron There is guard if (method.isAnnotationPresent(MethodXY.class)) ... so why null?
I meant your first method getMethodsAnnotatedWith, line 9.
@kliron Thank you for bringing this to my attention -- it was a quick copy paste and in this case that condition was just wrong. The code snipped has been adjusted.
|
4

try this code sample:

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.reflect.InvocationTargetException;

class AnotTest {
    public static void main(String... args) {
        AnnotationTest at = new AnnotationTest();
        for (Method m : at.getClass().getMethods()) {
           MethodXY mXY = (MethodXY)m.getAnnotation(MethodXY.class);
           if (mXY != null) {
               if (mXY.x() == 3 && mXY.y() == 2){
                   try {
                       m.invoke(at);
                   } catch (IllegalAccessException e) {
                       //do nothing;
                   } catch (InvocationTargetException o) {
                       //do nothing;
                   }
               }
           }
        }
    }
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    static public @interface MethodXY {
        public int x();
        public int y();
    }

    static class AnnotationTest {
        @MethodXY(x=5, y=5)
        public void myMethodA() {
            System.out.println("boo");
        }

        @MethodXY(x=3, y=2)
        public void myMethodB() {
            System.out.println("foo");
        }
    }
}

1 Comment

@tilaprimera creating new instance of AnnotationTest, taking all methods of the defining class, iterating through methods, on each of them trying to get annotation named MethodXY, if we can obtain it, then we're checking what x and y values it has, if they're 3 and 2 respectively, we're invoking that method.
1
private static final Method getMethodByAnnotation(Class<?> cla, Class<? extends Annotation> annotation,
        int methodIndex) {
    Stream<Method> stream = Arrays.stream(cla.getDeclaredMethods())
            .filter(m -> m.isAnnotationPresent(annotation));
    return methodIndex == 0 ? stream.findFirst().get() : stream.toArray(Method[]::new)[methodIndex];
}

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.