Enums and annotations · ch. 5, p. 42
Annotation retention and targets
@Retention decides whether an annotation survives to the class file and to runtime; @Target restricts where it may be written. Only RUNTIME retention is visible to reflection.
| Policy | Kept in .class | Visible to reflection | Typical use |
|---|---|---|---|
SOURCE | no | no | @Override, Lombok |
CLASS (default) | yes | no | bytecode tools |
RUNTIME | yes | yes | Spring, JPA, Jackson |
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
@Inherited
public @interface Audited {
String value() default "";
Level level() default Level.INFO;
}
Details that catch people out
@Inheritedapplies only to class-level annotations, and only down a superclass chain — never through interfaces.- Elements may be primitives,
String,Class, enums, other annotations, or arrays of these. Nothing else. - An element named
valuecan be written positionally:@Audited("payment").
Repeatable annotations
@Repeatable(Schedules.class)
public @interface Schedule { String cron(); }
This is compiler sugar. The two occurrences are wrapped in the container
annotation, so reflection must ask for Schedules — or use
getAnnotationsByType, which unwraps it for you.
3 questions on this concept Drill it