[Logo]
Forums Register Login
Get any value from annotated parameters for any unknown Annotation in runtime
Main question is: how to get any/all value from annotated parameters for any unknown Annotation in runtime?

More details: currently I'm learning Reflection API. There is a common to all very beginning studies task:
  • create custom Annotation which accept parameters for Method
  • create Class with some method annotated by custom Annotation with some values
  • implement another method which will invoke annotated method from that Class using parameters as values from annotation of that method

  • Standard way of solving this task is to get reference to known Annotation Class object A, and invoke method for object B, using values references from the object A.
    Something like this code:

    But this task and solution is too easy and I want to make my code to be independent from Annotation I'll create in code. I want to create smth. like library. User will path any Object which has annotated by any provided Annotation methods to my library method, and receive result of invoking of all methods which are available to input Object and marked by provided Annotaton.
    See commented questions.


    For example. Meaning there is such custom Annotation:

    Also there is such Class annotated by previous annotation:

    Need to create special Class and implement method to invoke all methods which are marked by special Annotation (for this case it's calculateSum and AnnotatedClass) passing parameters for invoked methods from their annotation. They are 3 and 7 for now. But compiler shouldn't know name of Annotation (current one is MyAnnotation) and what are the parameters (current paramOne and paramTwo).

    I don't have any problems with methods logic, etc. What I'm asking is some elegant way how to deal with Annotation and annotated parameters during runtime independently from any Annotation realization. Thanks in advance.
    You can get all annotations of a class or member, not just a specific one. You can then inspect them all through reflection. If I recall correctly annotation properties are just methods when using reflection.
    Wow Serhil, looks pretty cool what you are studying, which tutorial/course are you following? Really nice question
    Rob Spoor, basically yes, I can get array of any annotation methods via reflection. I'm struggling how to get values which are represent these methods parameters for specific object.
    For described situation I can get names of @MyAnnotation parameteres in runtime. They are "paramOne" and "paramTwo". But how can I get actual values @MyAnnotation(paramOne = 3, paramTwo = 7) which are 3 and 7?



    Here is list of Annotation methods Arrays.toString(annMethods):

    [public final boolean com.sun.proxy.$Proxy1.equals(java.lang.Object),
    public final java.lang.String com.sun.proxy.$Proxy1.toString(),
    public final int com.sun.proxy.$Proxy1.hashCode(),
    public final java.lang.Class com.sun.proxy.$Proxy1.annotationType(),
    public final int com.sun.proxy.$Proxy1.paramOne(),
    public final int com.sun.proxy.$Proxy1.paramTwo(),
    public static boolean java.lang.reflect.Proxy.isProxyClass(java.lang.Class),
    public static java.lang.Object java.lang.reflect.Proxy.newProxyInstance(java.lang.ClassLoader,java.lang.Class[],java.lang.reflect.InvocationHandler) throws java.lang.IllegalArgumentException,
    public static java.lang.reflect.InvocationHandler java.lang.reflect.Proxy.getInvocationHandler(java.lang.Object) throws java.lang.IllegalArgumentException,
    public static java.lang.Class java.lang.reflect.Proxy.getProxyClass(java.lang.ClassLoader,java.lang.Class[]) throws java.lang.IllegalArgumentException,
    public final void java.lang.Object.wait() throws java.lang.InterruptedException,
    public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException,
    public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException,
    public final native java.lang.Class java.lang.Object.getClass(),
    public final native void java.lang.Object.notify(),
    public final native void java.lang.Object.notifyAll()]



    Again, I need it's values, not just names...


    To be honest, I already solved this issue. But I don't like the way of my solution. It was based on investigation during debugging. That's why asking here how to deal with it in more elegant way. My solution is smth like that:
  • using reflection to get Annotation from annotated method in runtime
  • it will have private InvocationHandler h field
  • using reflection get value for memberValues Map<String, Object> of h field
  • these values are map of method_name -> value so I need to get value of each map entry

  • Here is clickable screenshot example of all of this stuff when I can see first parameter value paramOne = 3:


    And here is my "library Class" using this approach in GitHub if somebody is interested in.

    I believe there should be some better solution.


    Giovanni Montano, I'm following my local Java courses. It's even not in English, since I'm from Ukraine. Reflection is a first topic of Java EE course, which is following by 1,5 month Java OOP course. But it's not about course itself, it's about my own curiosity about reflection in Java
    (1 like)
    To call a method through reflection, simply call its invoke method. The first argument is the instance to call it on (in this case the annotation instance) or null for static methods. After that come the method arguments as varargs.

    Note that you should probably check the declaring class of the method as well, to get rid of all the "garbage" methods. Or even better, use getDeclaredMethods() instead of getMethods(). The latter will return all public methods you can call on instances of the class, even if they're defined on a super class. The former will return all methods that are defined on the class itself including non-public methods. However, since this is an annotation, all methods are public anyway.
    (1 like)
    Here's a little code snippet that can do what you want:

    Using the result of annotationType() will return your actual annotation class, whereas getClass() returns the actual class (com.sun.proxy.$Proxy1 in this case).
     

    Rob Spoor wrote:Using the result of annotationType() will return your actual annotation class, whereas getClass() returns the actual class (com.sun.proxy.$Proxy1 in this case).


    Thank you, that’s the heart of the matter! Also now I can better understand Annotations itself - previously I didn't realize there is possibility to invoke any annotation method just like it's regular method of Class instance.

    Finally, this code works like a charm for me, and that is exactly what I was looking for:


    This thread has been viewed 1242 times.

    All times above are in ranch (not your local) time.
    The current ranch time is
    Oct 22, 2018 23:30:43.