- Lire une annotation depuis un élément du programme
En Java, toute entité susceptible de porter une annotation — classe, constructeur, champ, méthode, package… — implémente l'interface java.lang.reflect.AnnotatedElement. Cette interface offre notamment les méthodes suivantes :
<T extends Annotation> T getAnnotation(Class<T> type)
Annotation[] getDeclaredAnnotations()
boolean isAnnotationPresent(Class<? extends Annotation> type)
Pour pouvoir interroger ces méthodes pendant l'exécution, l'annotation concernée doit être annotée avec @Retention(RetentionPolicy.RUNTIME).
- Exemple d'introspection
Définissons une annotation personnalisée conservée au runtime :
package dev.demo.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Action {
String nom();
int priorite() default 0;
}
Appliquons-la sur une méthode, puis lisons-la par réflexion :
package dev.demo.annotations;
import java.lang.reflect.Method;
public class Service {
@Action(nom = "demarrage", priorite = 1)
public void lancer() {
System.out.println("démarrage");
}
public static void main(String[] args) throws NoSuchMethodException {
Method m = Service.class.getMethod("lancer");
if (m.isAnnotationPresent(Action.class)) {
Action a = m.getAnnotation(Action.class);
System.out.println(a.nom() + " (priorité " + a.priorite() + ")");
System.out.println("type de l'annotation : " + a.annotationType());
}
}
}
- Restreindre les cibles avec @Target
L'annotation @Target, définie dans java.lang.annotation, indique les éléments du langage susceptibles de recevoir l'annotation. Ses valeurs sont les constantes de l'énumération ElementType :
TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR,
LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, MODULE, TYPE_PARAMETER, TYPE_USE
Exemple d'annotation limitée aux classes et aux méthodes :
package dev.demo.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Tracable {
String valeur() default "";
}
- Inclure l'annotation dans la documentation avec @Documented
Si une annotation porte @Documented, les outils de génération de documentation, tels que Javadoc, la mentionneront dans la page de l'élément annoté.
package dev.demo.annotations;
import java.lang.annotation.Documented;
@Documented
public @interface Notice {
String message();
}
- Transmettre une annotation aux sous-classes avec @Inherited
Lorsqu'une annnotation est annotée avec @Inherited et qu'elle s'aplique à une classe, les classes filles héritent de cette annotation. Cela ne s'applique pas aux interfaces ni aux méthodes redéfinies.
package dev.demo.annotations;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface Role {
String nom();
}
@Role(nom = "admin")
public class Compte { }
public class CompteAdmin extends Compte { }
// CompteAdmin.class.getAnnotation(Role.class) renvoie l'annotation héritée
- Rappel sur les méta-annotations et les valeurs par défaut
Java fournit quatre méta-annotations standard dans le package java.lang.annotation :
- @Target : cibles autorisées.
- @Retention : durée de vie (
SOURCE,CLASSouRUNTIME). - @Documented : inclusion dans la documentation publique.
- @Inherited : transmission aux classes filles.
Une annotation personnalisée se déclare avec @interface. Chaque méthode de l'annotation représente un paramètre ; son type de retour est le type du paramètre. Seuls les types suivants sont autorisés : types primitifs, String, Class, enum, une autre annotation, ou un tableau de ces types. Une valeur par défaut s'indique via default.
public @interface Config {
String hote() default "localhost";
int port() default 8080;
}
Les éléments non primitifs ne peuvent valoir null ; on utilise souvent une chaîne vide ou -1 comme conevntion pour indiquer l'absence de valeur explicite.