Annotations
- Create, apply, and process annotations
Application(s)
The notion of annotation is an additional notion to the previous notions of
class
andinterface
. 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
- No arguments in methods;
- Returned types must be primitive types (
boolean
,byte
…), enumerated types,String
,Class
or arrays of all of these types;- No
throws
clause;- An annotation with only one property leads to the use of the
value
name for this property.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=[™])
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.Deprecated
@java.lang.annotation.Documented
@java.lang.annotation.Inherited
@java.lang.Override
@java.lang.annotation.Retention
@java.lang.SuppressWarnings
@java.lang.annotation.Target
@java.lang.annotation.Target
This annotation has a unique property (named
value
) of type array ofjava.lang.annotation.ElementType
with the following possible values:
ANNOTATION_TYPE
CONSTRUCTOR
FIELD
LOCAL_VARIABLE
METHOD
PACKAGE
PARAMETER
TYPE
- From Java 8:
TYPE_PARAMETER
andTYPE_USE
- From Java 9:
MODULE
@java.lang.annotation.Retention
This annotation has a unique property (named
value
) of type array ofjava.lang.annotation.RetentionPolicy
with the following possible values:
SOURCE
(ignored by compiler; used by a linter typically…)CLASS
(ignored by JVM)RUNTIME
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; }
@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 { …
@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!
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) { … }
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
whileAnother_class
inherits fromMy_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=[™])