What is @Documented, and how do you read annotation values at runtime via reflection?
answer
- @Documented = annotation shows in Javadoc
- Default: annotations omitted from Javadoc
- Read via reflection: getAnnotation(...).element()
- Only RUNTIME annotations are readable
- isAnnotationPresent / getAnnotationsByType helpers
basics
~20 s@Documented makes an annotation show up in the generated Javadoc of whatever it is applied to. To read an annotation's values while the program runs, you use reflection (getAnnotation) and call the annotation's element methods — but only if it is kept at RUNTIME.
solid answer
~40 s@Documented is a meta-annotation with one job: if your annotation is @Documented, then when Javadoc is generated for an element that uses it, the annotation appears in that element's documentation. By default annotations are omitted from Javadoc. It has no effect on compilation or runtime behavior. Reading annotation values at runtime is done through the Reflection API: get the AnnotatedElement (a Class, Method, Field via getDeclaredMethod etc.), call getAnnotation(MyAnno.class) to get the annotation instance (or null if absent), then invoke its element accessor methods like myAnno.value(). This only works when the annotation is RUNTIME-retained; otherwise getAnnotation returns null. Helper calls include isAnnotationPresent, getAnnotations (all, inheritance-aware), and getAnnotationsByType (for repeatables).
code
java · 13 linesimport java.lang.annotation.*;
import java.lang.reflect.Field;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@interface Column { String name(); boolean nullable() default true; }
class User { @Column(name="email", nullable=false) String email; }
// Field f = User.class.getDeclaredField("email");
// Column c = f.getAnnotation(Column.class); // null unless RUNTIME
// String n = c.name(); // "email"
// boolean nn = c.nullable(); // falsego deeper
Knows @Documented surfaces an annotation in Javadoc and that you read annotation values with getAnnotation plus the element methods.
Connects readability to RUNTIME retention and knows the family of AnnotatedElement methods (isAnnotationPresent, getAnnotations, getAnnotationsByType).
Explains the proxy nature of returned instances and the retention dependency, and chooses the right read method for inheritance/repeatables.
Frames annotation reflection cost and caching for framework-scale scanning and sets documentation/visibility conventions (@Documented) for public annotation APIs.
## Two small but commonly-paired topics This covers `@Documented` (a meta-annotation) and the basic mechanics of *reading* annotations at runtime — they come up together because both are about what an annotation 'exposes'. ## @Documented An **annotation** is an `@`-marker on code. **Javadoc** is the HTML API documentation the JDK generates from source comments. By default, when Javadoc documents a method or class, it does **not** list the annotations applied to it. Marking your annotation type `@Documented` flips that: the annotation will be **included in the generated Javadoc** of any element it is placed on. That is its *entire* purpose — it changes nothing about compilation or runtime semantics; it is purely a documentation-visibility switch. ```java @Documented @Retention(RetentionPolicy.RUNTIME) @interface ApiStable {} ``` ## Reading annotations at runtime via reflection **Reflection** is Java's ability to inspect classes, methods, and fields at runtime. Anything you can attach an annotation to implements `AnnotatedElement`, which exposes annotation-reading methods: - `isAnnotationPresent(MyAnno.class)` -> boolean: is it there? - `getAnnotation(MyAnno.class)` -> the annotation instance, or `null` if absent. The returned object is a dynamic proxy implementing the annotation interface. - `getAnnotations()` -> all annotations (honors @Inherited up the class chain). - `getDeclaredAnnotations()` -> only directly declared ones. - `getAnnotationsByType(MyAnno.class)` -> all instances, container-aware for @Repeatable. Once you have the instance, you read its values by calling its **element methods** — the annotation's members look like no-arg methods: ```java @Retention(RetentionPolicy.RUNTIME) @interface Column { String name(); boolean nullable() default true; } class User { @Column(name="email", nullable=false) String email; } Field f = User.class.getDeclaredField("email"); Column c = f.getAnnotation(Column.class); // proxy instance String n = c.name(); // "email" boolean nn = c.nullable(); // false ``` ## The critical dependency on retention All of this **only works for RUNTIME-retained annotations**. If `@Column` were SOURCE- or CLASS-retained, `getAnnotation(Column.class)` would return `null` and you would get a `NullPointerException` calling `c.name()`. This ties directly back to `@Retention`: the runtime-reading story is only available when you chose RUNTIME. ## Putting it together `@Documented` decides *documentation* visibility; `@Retention(RUNTIME)` decides *reflection* visibility; the Reflection API then lets you fetch the instance and call its element methods to act on the metadata — which is exactly how frameworks turn annotations into behavior.
- If getAnnotation(MyAnno.class) returns null even though you wrote the annotation, what is the most likely cause?The annotation is not RUNTIME-retained (it defaults to CLASS if @Retention is omitted, or is SOURCE), so reflection cannot see it. Add @Retention(RetentionPolicy.RUNTIME) to the annotation declaration.
saying these in an interview costs you the question
- Thinking @Documented changes runtime or compile behavior — it only affects Javadoc.
- Trying to read a SOURCE/CLASS-retained annotation via reflection.
- Forgetting that getAnnotation returns null (and will NPE on the accessor) when the annotation is absent or not RUNTIME.
- Confusing @Documented with @Inherited.