Accès rapide :
Qu'est-ce qu'une annotation Java ?
Annotations relatives à la compréhension du code
Annotations propagées dans le code binaire
La JSR 250 et le package javax.annotations
Une annotation est un marqueur particulier (introduit par un caractère @
) permettant d'ajouter une méta-données à un élément de votre programme.
On peut ajouter une annotation à un type (classe, interface, type énuméré, ...), un attribut, une méthode ou encore un constructeur.
En soi, une annotation ne fait pas grand-chose : il faut qu'un framework (ou une librairie) recherche ces annotations pour les traiter.
Les annotations Java étant des méta-données, pour les rechercher et les manipuler, on doit utiliser le moteur de réflexion Java.
Il existe cependant quelques annotations qui n'ont de sens que pour la compréhension du code source, par exemple l'annotation @Override
.
Ce type d'annotations est non manipulable par le moteur de réflexion.
On dit d'une telle annotation qu'elle a une rétention de type « Source ». Dit autrement, l'annotation n'est pas stockée dans le .class
produit par le compilateur.
Il existe quelques annotations de ce type. La plus connue est certainement java.lang.@Override
. Elle permet d'indiquer au développeur relisant le code qu'une méthode réalise une redéfinition :
il existe donc une méthode de signature équivalente sur un type parent (classe héritée ou interface implémentée). Le cas le plus classique d'utilisation de cette annotation consiste en la redéfinition de la
méthode toString
. En voici un exemple, pour rappel.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package fr.koor.annotations; public class Start { public static void main( String[] args ) throws Exception { Start instance = new Start(); System.out.println( instance ); } @Override public String toString() { return "This is my toString implementation"; } } |
toString
en utilisant les assistants de votre IDE.
Sous Eclipse, placez-vous à l'endroit ou vous souhaitez générer la méthode et saisissez-y le mot toString
. Appuyez ensuite sur la séquence de touche CTRL+ESPACE.
La méthode doit être générée automatiquement et vous devriez y retrouver l'annotation @Override
.
Une autre annotation n'ayant du sens qu'au sein du code source est l'annotation java.lang.SuppressWarnings
. Elle permet d'indiquer au compilateur ou à votre IDE de ne pas tenir compte
de certains avertissements (warnings). Voici un exemple d'utilisation de cette annotation pour demander à ne pas signaler les éléments de code non utilisés.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package fr.koor.annotations; @SuppressWarnings( "unused" ) // Essayez de supprimer cette annotation. public class Start { private void unusedMethod() { // Un warning peut être produit, car la méthode // est privée et non utilisée dans la classe. } public static void main( String[] args ) throws Exception { int unusedInteger = 10; System.out.println( "Bye bye" ); } } |
Pour les autres annotations, il faut savoir qu'elles sont poussées dans le fichier .class
produit par le compilateur.
Il est donc possible de les manipuler au « runtime » (durant l'exécution de votre programme) via le moteur de réflexion Java.
C'est le cas de l'annotation java.lang.Deprecated
. Voici un exemple de code listant l'ensemble de méthodes dépréciées portées par la classe.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
package fr.koor.annotations; import java.lang.reflect.Method; public class Start { public static void methode1() {} @Deprecated public static void methode2() {} public static void methode3() {} @Deprecated public static void methode4() {} public static void main( String[] args ) throws Exception { // Récupération des méta-données à partir de la classe. Class<Start> metadata = Start.class; // On récupère les méthodes déclarées dans le type courant. Method [] methods = metadata.getDeclaredMethods(); // On affiche des informations sur les méthodes dépréciées de la classe. for( Method method : methods ) { if ( method.isAnnotationPresent( Deprecated.class ) ) { System.out.println( method.getName() ); } } } } |
Et voici les résultats produits par ce programme.
methode2 methode4
La JSR 250 définit un ensemble d'annotations communes (Common Annotations) pour la plate-forme Java. Voici un descriptif de ces annotations.
@Generated : cette annotation est utilisée pour indiquer qu'un code a été produit par un générateur. Bien entendu, elle est de rétention source et peut être utilisées sur tous les éléments de code (classes, interfaces, méthodes, constructeurs, ...). Malgré son existence, rares sont les générateurs ajoutant cette annotation dans le code qu'ils produisent. Voici un exemple d'utilisation.
1 2 3 4 5 6 7 |
@Generated( value = "Nom du générateur de code", // Obligatoire comments = "Explications sur l'intérêt de ce code", // Facultatif (String) date = "2019/04/02" // Facultatif (String) ) public class GeneratedClass() { } |
@PostConstruct : permet d'indiquer qu'une méthode est à exécuter après sa phase initialisation (constructeur + setters).
Cette annotation doit, bien entendu, être accessible au runtime pour être trouvée par le système qui va coordonner les appels aux méthodes associées.
Cette annotation est intimement liée à l'annotation @PreDestroy
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
package fr.koor.annotations; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; public class ABean { private int attribute1 = 0; private int attribute2 = 0; public ABean() { } public int getAttribute1() { return attribute1; } public int getAttribute2() { return attribute2; } public void setAttribute1( int attribute1 ) { this.attribute1 = attribute1; } public void setAttribute2( int attribute2 ) { this.attribute2 = attribute2; } @PostConstruct public void postInitialisation() { System.out.println( "Intialisation finalized" ); } @PreDestroy public void preFinalize() { System.out.println( "Now this instance is eligible for garbage collecting" ); } } |
@PreDestroy : permet d'indiquer qu'une méthode est à exécuter avant la libération de l'objet. Cette annotation doit, bien entendu, être accessible au runtime pour être trouvée
par le système qui va coordonner les appels aux méthodes associées. Cette annotation est intimement liée à l'annotation @PostConstruct
.
Consultez l'extrait de code précédent pour en voir un exemple d'utilisation.
@Resource : permet d'associer à un attribut ou à un setter une JNDI. JNDI (Java Naming and Directory Interface) est une API permettant d'accéder à des ressources stockées dans une base de données hiérarchique. Les serveurs d'applications Java EE propose, notamment, une base de données de ce type : dans ce cas, le serveur aura la responsabilité de retrouver ces annotations et d'injecter les instances de ressources dans les beans considérés. Voici un exemple d'utilisation.
1 2 3 4 5 6 7 |
public class ABean { @Resource(name="connectionName") private java.sql.Connection connection; // Suite de la classe. } |
@Resources : représente une collection de ressources JNDI. Chaque instance de la collection se définit via une annotation @Resource
.
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :