Tuesday, December 23, 2008

Reflecting on Annotations

          The easiest way to check for an annotation is by using the isAnnotationPresent() method

­          This lets us specify the annotation to check for, and get a true/false result

public void testAnnotnPresent(PrintStream out) throws Exception {

      Class c = Super.class;

boolean inProgr = c.isAnnotationPresent(InProgress.class);

if(inProgr) out.println(“Super is in progress”);

else out.println(“Super is not in progress”);

 

}

­          This also lets us take advantage of the Inherited annotation

­          Although the Sub is not marked as in progress, it inherits from Super, which is in progress

­          Once the method in question is located, that method can be queried for a specific annotation using getAnnotation()

Class c = AnnotationTester.class;

MethodElement element = c.getMethod(“calculateInterest”,

                                    float.class, float.class);

GroupTODO groupTodo = element.getAnnotation(GroutpTODO.class);

String assignedTo = groupTodo.assignedTo();

out.println(“TODO Item on Annotation Tester is assigned to: ” +

assignedTo);

­          We must have to know exactly what we’re looking for – this is one of the few drawbacks of getAnnotation()

­           

­          We can use getAnnotations(), if we’re trying to locate all annotations for a program element, or if we need to iterate through all annotations looking for a specific one

­          Following is a simple utility method that prints out all annotations for a supplied element

public void printAnnotations(AnnotatedElement e) {

      System.out.println(“Annotations for “ + e.toString());

      Annotation[] annotations = e.getAnnotations();

for(Annotation a : annotations) {

      System.out.println(a.annotationType().getName());

}

}

­          The getAnnotations() method prints both declared as well as inherited annotations

­          To get declared annotations alone, we need to use getDeclaredAnnotations() method

­          java.lang.reflect.AnnotatedElement is an interface that the reflection constructs like Method, Class etc. implement

­          It allows access to the annotation methods

­          The core reflection constructs all implement this interface –

o        Class

o        Constructor

o        Field

o        Method

o        Package

o        AccessibleObject

­          This allows all the above elements to be introspected for annotations

­          All these element types provide the following methods as a result of implementing AnnotatedType

o        public Annotation getAnnotation(Class annotationType)

o        public Annotation[] getAnnotations()

o        public Annotation[] getDeclaredAnnotations()

o        public boolean isAnnotationPresent(Class annotationType)

­          Since any Java program element can be treated as an AnnotatedType, we can always get at an element’s annotations using these methods

­           

­          Reflection on annotations only works for annotation types that have Runtime retention

­          Even if the annotation is retained at compilation, if the VM doesn’t load this retention at class-load time, then reflection can’t pick up the annotation

­          Deprecation does not have runtime retention – it has source retention

­          So it is undetectable through Java reflection

­           

No comments: