More details: currently I'm learning Reflection API. There is a common to all very beginning studies task:
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.
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:
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
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.
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: