message.setDetail(errorLabel);
throw new ValidatorException(message);
}
}
}
</syntaxhighlight>
== Processing ==
When Java source code is compiled, annotations can be processed by compiler plug-ins called annotation processors. Processors can produce informational messages or create additional Java source files or resources, which in turn may be compiled and processed. However, annotation processors cannot modify the annotated code itself. (Code modifications may be implemented using methods beyond the Java Language Specification.) The Java compiler conditionally stores annotation metadata in the class files, if the annotation has a <code>RetentionPolicy</code> of <code>CLASS</code> or <code>RUNTIME</code>. Later, the [[Java virtual machine|JVM]] or other programs can look for the metadata to determine how to interact with the program elements or change their behavior.
In addition to processing an annotation using an annotation processor, a Java programmer can write their own code that uses reflections to process the annotation. [[Java Platform, Standard Edition|Java SE]] 5 supports a new interface that is defined in the <code>java.lang.reflect</code> package. This package contains the interface called <code>AnnotatedElement</code> that is implemented by the Java reflection classes including <code>Class</code>, <code>Constructor</code>, <code>Field</code>, <code>Method</code>, and <code>Package</code>. The implementations of this interface are used to represent an annotated element of the program currently running in the Java Virtual Machine. This interface allows annotations to be read reflectively.
The <code>AnnotatedElement</code> interface provides access to annotations having <code>RUNTIME</code> retention. This access is provided by the <code>getAnnotation</code>, <code>getAnnotations</code>, and <code>isAnnotationPresent</code> methods. Because annotation types are compiled and stored in byte code files just like classes, the annotations returned by these methods can be queried just like any regular Java object. A complete example of processing an annotation is provided below:
<syntaxhighlight lang=Java>
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
// This is the annotation to be processed
// Default for Target is all Java Elements
// Change retention policy to RUNTIME (default is CLASS)
@Retention(RetentionPolicy.RUNTIME)
public @interface TypeHeader {
// Default value specified for developer attribute
String developer() default "Unknown";
String lastModified();
String [] teamMembers();
int meaningOfLife();
}
</syntaxhighlight>
<syntaxhighlight lang=Java>
// This is the annotation being applied to a class
@TypeHeader(developer = "Bob Bee",
lastModified = "2013-02-12",
teamMembers = { "Ann", "Dan", "Fran" },
meaningOfLife = 42)
public class SetCustomAnnotation {
// Class contents go here
}
</syntaxhighlight>
<syntaxhighlight lang=Java>
// This is the example code that processes the annotation
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
public class UseCustomAnnotation {
public static void main(String [] args) {
Class<SetCustomAnnotation> classObject = SetCustomAnnotation.class;
readAnnotation(classObject);
}
static void readAnnotation(AnnotatedElement element) {
try {
System.out.println("Annotation element values: \n");
if (element.isAnnotationPresent(TypeHeader.class)) {
// getAnnotation returns Annotation type
Annotation singleAnnotation =
element.getAnnotation(TypeHeader.class);
TypeHeader header = (TypeHeader) singleAnnotation;
System.out.println("Developer: " + header.developer());
System.out.println("Last Modified: " + header.lastModified());
// teamMembers returned as String []
System.out.print("Team members: ");
for (String member : header.teamMembers())
System.out.print(member + ", ");
System.out.print("\n");
System.out.println("Meaning of Life: "+ header.meaningOfLife());
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
|