Les annotations Java sont marquées d'une annotation @Target
Pour déclarer les éventuels points de jointure qui peuvent être décorés par cette annotation. Les valeurs TYPE
, FIELD
, METHOD
, etc. de l'énumération ElementType
sont claires et simplement compréhensibles.
POURQUOI pour utiliser la valeur @Target(ANNOTATION_TYPE)
? À quoi servent les annotations annotées? Quelle est leur contribution? Donnez-moi un explication d'une idée comment cela fonctionne et pourquoi je devrais l'utiliser. Un exemple déjà existant et bien connu de son utilisation serait également très bien.
Vous pouvez utiliser une annotation annotée pour créer une méta-annotation, par exemple, envisagez cette utilisation de @Transactional
au printemps:
/**
* Shortcut and more descriptive "alias" for {@code @Transactional(propagation = Propagation.MANDATORY)}.
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional(propagation = Propagation.MANDATORY)
public @interface RequiresExistingTransaction {
}
Lorsque vous activez Spring pour traiter le @Transactional
annotation, il recherchera les classes et méthodes qui portent @Transactional
o toute méta-annotation de celui-ci (une annotation qui est annotée avec @Transactional
).
Quoi qu'il en soit, ce n'était qu'un exemple concret de la façon dont on peut utiliser une annotation annotée. Je suppose que ce sont principalement des frameworks comme Spring où il est logique de les utiliser.
Chaque annotation annotée par @Target(ElementType.ANNOTATION_TYPE)
est appelée Meta-annotation
. Cela signifie que vous pouvez définir vos propres annotations personnalisées qui sont une fusion de nombreuses annotations combinées en une seule annotation pour créer composed annotations
.
Un bon exemple de Android world est StringDef
Indique que l'élément String annoté représente un type logique et que sa valeur doit être l'une des constantes nommées explicitement.
@Retention(SOURCE)
@Target({ANNOTATION_TYPE})
public @interface StringDef {
/** Defines the allowed constants for this element */
String[] value() default {};
}
//--
@Retention(SOURCE)
@StringDef({POWER_SERVICE, WINDOW_SERVICE, LAYOUT_INFLATER_SERVICE})
public @interface ServicesName {}
public static final String POWER_SERVICE = "power";
public static final String WINDOW_SERVICE = "window";
public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";
//--
@StringDef({SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY})
@Retention(RetentionPolicy.SOURCE)
public @interface WeekDays {}
public static final String SUNDAY = "sunday";
public static final String MONDAY = "monday";
public static final String TUESDAY = "tuesday";
public static final String WEDNESDAY = "wednesday";
public static final String THURSDAY = "thursday";
public static final String FRIDAY = "friday";
public static final String SATURDAY = "saturday";
...
public abstract Object getSystemService(@ServicesName String serviceName);
public abstract Object getDayOfWeek(@WeekDays String weekDay);
L'inspecteur de code traitera @ServicesName
Et @WeekDays
De la même manière que @StringDef
. Par conséquent, nous pouvons créer autant de nomméStringDef
que nécessaire et remplacer un ensemble de constantes. @Target(ElementType.ANNOTATION_TYPE)
c'est un outil qui permet d'étendre l'utilisation des annotations.
Par exemple, si l'annotation ressemble à
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface SomeAnnotation {
String description() default "This is example for class annotation";
}
le compilateur complane dans cette situation
@SomeAnnotation
public class SomeClass {
@SomeAnnotation // here it's complaning
public void someMethod(){}
}
Si vous changez
@Target(ElementType.TYPE)
à
@Target({ElementType.METHOD, ElementType.TYPE})
il ne se plaindra plus.