How to get annotation class name, attribute values using reflection

I know if we know the annotation class, we can easily get the specific annotation and access its attribute. For example:

field.getAnnotation(Class<T> annotationClass) 

Which will return a reference of specific annotation interface, so you can easily access its values.

My question is if I have no pre knowledge about the particular annotations class. I just want to use reflection to get all the annotation class name and their attributes at run-time for the purpose of dumping the class information for example as a JSON file. How can I do it in an easy way.

Annotation[] field.getAnnotations();

This method will only return dynamic proxies of the annotation interfaces.


Contrary to what one might expect, the elements of an annotation are not attributes - they are actually methods that return the provided value or a default value.

You have to iterate through the annotations' methods and invoke them to get the values. Use annotationType() to get the annotation's class, the object returned by getClass() is just a proxy.

Here is an example which prints all elements and their values of the @Resource annotation of a class:

@Resource(name = "foo", description = "bar")
public class Test {

    public static void main(String[] args) throws Exception {

        for (Annotation annotation : Test.class.getAnnotations()) {
            Class<? extends Annotation> type = annotation.annotationType();
            System.out.println("Values of " + type.getName());

            for (Method method : type.getDeclaredMethods()) {
                Object value = method.invoke(annotation, (Object[])null);
                System.out.println(" " + method.getName() + ": " + value);
            }
        }

    }
}

Output:

Values of javax.annotation.Resource
 name: foo
 type: class java.lang.Object
 lookup: 
 description: bar
 authenticationType: CONTAINER
 mappedName: 
 shareable: true

Thanks to Aaron for pointing out the you need to cast the null argument to avoid warnings.


Just to follow up on the answer above (I don't have enough rep to reply to it):

method.invoke(annotation, null)

should be changed to the following, otherwise it throws an exception:

method.invoke(annotation, (Object[])null) or method.invoke(annotation, new Object[0])