2. History
The Java platform has had various ad-hoc annotation
mechanisms—for example, the transient modifier, or the
@deprecated javadoc tag.
The general purpose annotation (also known as metadata)
facility was introduced to the Java Community Process as JSR-175
in 2002 and approved in September 2004.
Annotations became available in the language itself beginning
with version 1.5 of the JDK. A provisional interface for compile-
time annotation processing was provided by the apt tool in JDK
version 1.5, and was formalized through JSR-269 and integrated
into the javac compiler in version 1.6.
3. What is it
Annotations do not directly affect program semantics, but they
do affect the way programs are treated by tools and libraries, which
can in turn affect the semantics of the running program.
Annotations can be read from source files, class files, or
reflectively at run time.
Annotations complement javadoc tags. In general, if the
markup is intended to affect or produce documentation, it should
probably be a javadoc tag; otherwise, it should be an annotation.
4. Built-In Annotations applied
to java code
@Deprecated—the @Deprecated annotation indicates that the marked element is
deprecated and should no longer be used. The compiler generates a warning
whenever a program uses a method, class, or field with the @Deprecated
annotation. When an element is deprecated, it should also be documented using
the Javadoc @deprecated tag, as shown in the following example. The use of the
"@" symbol in both Javadoc comments and in annotations is not coincidental —
they are related conceptually. Also, note that the Javadoc tag starts with a
lowercase "d" and the annotation starts with an uppercase "D".
/**
* @deprecated
* explanation of why it was deprecated
*/
@Deprecated
static void deprecatedMethod() { }
5. Built-In Annotations applied
to java code
@Override—the @Override annotation informs the compiler that
the element is meant to override an element declared in a
superclass). While it's not required to use this annotation when
overriding a method, it helps to prevent errors. If a method marked
with @Override fails to correctly override a method in one of its
superclasses, the compiler generates an error.
// mark method as a superclass method
// that has been overridden
@Override
int overriddenMethod() { }
6. Built-In Annotations applied
to java code
@SuppressWarnings—the @SuppressWarnings annotation tells the compiler to
suppress specific warnings that it would otherwise generate.
// use a deprecated method and tell compiler not to generate a
warning@SuppressWarnings("all", "deprecation", "unchecked",
"fallthrough", "path", "serial", "finally")
In the example below, a deprecated method is used and the compiler would
normally generate a warning. In this case, however, the annotation causes the
warning to be suppressed.
// use a deprecated method and tell
// compiler not to generate a warning
@SuppressWarnings("deprecation")
void useDeprecatedMethod() {
// deprecation warning - suppressed
objectOne.deprecatedMethod();
}
7. Built-In Annotations applied
to other annotations
• @Target - Marks another annotation to restrict what kind of
java elements the annotation may be applied to.
• @Retention - Specifies how the marked annotation is stored --
Whether in code only, compiled into the class, or available at
runtime through reflection.
• @Documented - Marks another annotation for inclusion in the
documentation.
• @Inherited - Marks another annotation to be inherited to
subclasses of annotated class (by default annotations are not
inherited to subclasses).
8. @Target
You can specify a single target using a single value or multiple
ones using an array.
@Target ({
ElementType.PACKAGE,
ElementType.TYPE,
ElementType.CONSTRUCTOR,
ElementType.METHOD,
ElementType.PARAMETER,
ElementType.FIELD,
ElementType.LOCAL_VARIABLE,
ElementType.ANNOTATION_TYPE
})
9. @RetentionPolicy
• RetentionPolicy.SOURCE retains an annotation only in
the source file and discards it during compilation.
• RetentionPolicy.CLASS stores the annotation in the .class
file but does not make it available during runtime.
• RetentionPolicy.RUNTIME stores the annotation in the
.class file and also makes it available during runtime.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TryThis {
String [] value();
}
10. Annotation attributes
Return types are restricted to primitives, String, Class, enums, annotations, and
arrays of the preceding types. Methods can have default values.
Here is an example annotation type declaration:
/**
* Describes the Request-For-Enhancement(RFE) that led
* to the presence of the annotated API element.
*/
public @interface RequestForEnhancement {
int id();
String synopsis();
String engineer() default "[unassigned]";
String date(); default "[unimplemented]";
String[] text();
}
11. RetentionPolicy (CLASS vs
RUNTIME)
RUNTIME: Annotations are to be recorded in the class file by the compiler and
retained by the VM at run time, so they may be read reflectively.
CLASS: Annotations are to be recorded in the class file by the compiler but need
not be retained by the VM at run time.
skaffman (TM)
In practice, I'm not aware of any use-cases for CLASS. It would only be useful if
you wanted to read the bytecode programmatically, as opposed to via the
classloader API, but that's a very specialised case, and I don't know why you
wouldn't just use RUNTIME.
Ironically, CLASS is the default behaviour.
14. Annotation-based test
framework
To tie it all together, we'll build a simple annotation-based test
framework. First we need a marker annotation type to indicate that a
method is a test method, and should be run by the testing tool:
import java.lang.annotation.*;
/**
* Indicates that the annotated method is a test method.
* This annotation should be used only on parameterless static methods.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test { }
15. Annotation-based test
framework
Note that the annotation type declaration is itself
annotated. Such annotations are called meta-annotations.
The first (@Retention(RetentionPolicy.RUNTIME))
indicates that annotations with this type are to be retained by
the VM so they can be read reflectively at run-time.
The second (@Target(ElementType.METHOD))
indicates that this annotation type can be used to annotate
only method declarations.
16. Annotation-based test
framework
Here is a sample program, some of whose methods are
annotated with the above interface:
public class Foo {
@Test public static void m1() { }
public static void m2() { }
@Test public static void m3() { }
public static void m4() { }
@Test public static void m5() { }
}
17. Annotation-based test
framework
import java.lang.reflect.*;
public class RunTests {
public static void main(String[] args) throws Exception {
int passed = 0, failed = 0;
for (Method m : Class.forName(args[0]).getMethods()) {
if (m.isAnnotationPresent(Test.class)) {
try {
m.invoke(null);
passed++;
} catch (Throwable ex) {
System.out.printf("Test %s failed: %s %n", m, ex.getCause());
failed++;
}
}
}
System.out.printf("Passed: %d, Failed %d%n", passed, failed);
}