Java Annotations


Creative Commons License
This -Java Annotations- tutorial is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License
Java SE 11 Developer certification (exam number 1Z0-819) here

Annotations

Characterization

Application(s)

The notion of annotation is an additional notion to the previous notions of class and interface. Java annotations may be (incompletely) compared to C++ compilation macro-statements, for instance:

#ifndef _symbol
#define _symbol
…
#endif

However, Java annotations have higher scope and power than C++ macro-statements since they may persist and be used at run-time (java.lang.reflect API).

Sample

An annotation can be defined as follows:

public @interface Copyright { // Please note the '@' just before 'interface'!
    char[] codes() default {'\u00AE','\u00A9','\u2122'};
    String author() default "Franck Barbier";
}

Rules

Interesting capabilities: default values for properties may be set up by means of the default keyword.

What is the purpose of Java annotations?

Java annotations mainly serve as markers for the Java code in order to be interpreted at compilation time, deployment time or run-time, for example (runtime usage):

@Copyright(codes = {'\u2122'},author = "Anonymous")
public class My_class {
    public static void main(String[] args) {
        java.lang.annotation.Annotation annotations[] = (new My_class()).getClass().getAnnotations(); // Access by introspection
        for(int i = 0;i < annotations.length;i++) System.out.println("Annotation #" + i + ": " + annotations[i].toString());
    }
}

Display:

Annotation #0: @com.FranckBarbier.Java._Annotations.Copyright(author=Anonymous, codes=[™])
Existing (core) annotations

In Java SE and Java EE frameworks (from Java SE 5 and Java EE 5), many predefined annotations exist. The seven core annotations are:

@java.lang.annotation.Target

This annotation has a unique property (named value) of type array of java.lang.annotation.ElementType with the following possible values:

@java.lang.annotation.Retention

This annotation has a unique property (named value) of type array of java.lang.annotation.RetentionPolicy with the following possible values:

Current definition (Java 11 API) ⤳ here

@Documented
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = java.lang.annotation.ElementType.ANNOTATION_TYPE)
public @interface Retention {
    java.lang.annotation.RetentionPolicy value() default java.lang.annotation.RetentionPolicy.CLASS;
}
Revisiting the user-defined @Copyright annotation
@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target({java.lang.annotation.ElementType.PACKAGE,java.lang.annotation.ElementType.TYPE})
public @interface Copyright { …
Resource injection based on @javax.annotation.Resource

Note

javax.annotation is no longer a package in Java 11. Inclusion may then be based on Maven for instance.

<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>

Definition

@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.TYPE,java.lang.annotation.ElementType.FIELD,java.lang.annotation.ElementType.METHOD})
public @interface Resource { …

Usage

@javax.annotation.Resource
private javax.transaction.UserTransaction _utx; // No instantiation required!
Annotating a method parameter

Defining the annotation itself:

@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@java.lang.annotation.Target(value = java.lang.annotation.ElementType.PARAMETER)
public @interface May_be_null { }

Using it:

public void my_function(@May_be_null Object my_object) { … }
Annotation inheritance

Annotations may be inherited provided that they are declared as inheritable, example:

@java.lang.annotation.Inherited
public @interface Copyright { …

My_class is already annotated with @Copyright while Another_class inherits from My_class:

public class Another_class extends My_class { …

Testing inherited annotations

Declared annotations…:

java.lang.annotation.Annotation other_annotations[] = (new Another_class()).getClass().getDeclaredAnnotations();
for(int i = 0;i < other_annotations.length;i++) System.out.println("Annotation #" + i + ": " + other_annotations[i].toString()); // Nothing is displayed!

… versus owned annotations:

java.lang.annotation.Annotation other_annotations[] = (new Another_class()).getClass().getAnnotations();
for(int i = 0;i < other_annotations.length;i++) System.out.println("Annotation #" + i + ": " + other_annotations[i].toString());

Display:

Annotation #0: @com.FranckBarbier.Java._Annotations.Copyright(author=Anonymous, codes=[™])