Retention Policies and Target Types
Choose SOURCE, CLASS, or RUNTIME retention and restrict target elements with @Target.
Retention Policies and Target Types is a free Java Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Java Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
The Three Retention Policies
SOURCE: discarded by the compiler (only useful to APT). CLASS: written to .class files, not available at runtime. RUNTIME: available via reflection. Most framework annotations use RUNTIME.
SOURCE Retention: Compile-Time Only
SOURCE annotations are processed by annotation processors and then discarded. @Override and @SuppressWarnings are SOURCE — they inform the compiler but are not in the .class file.
@Retention(RetentionPolicy.SOURCE)
public @interface GenerateBuilder {}
// APT generates a Builder class when it sees @GenerateBuilder
// The annotation itself disappears from the compiled outputCLASS Retention: Bytecode Analysis
CLASS annotations are included in .class files for bytecode analysis tools (PMD, FindBugs, ASM) but are NOT readable at runtime via reflection.
@Retention(RetentionPolicy.CLASS)
public @interface ThreadSafe {}
// Visible in bytecode, invisible to Class.getAnnotation() at runtimeRUNTIME Retention: Reflective Processing
RUNTIME annotations survive to runtime and can be read with getAnnotation(). Spring, JUnit, Jackson, and Hibernate use RUNTIME retention.
@Retention(RetentionPolicy.RUNTIME)
public @interface Route {
String path();
String method() default "GET";
}
// At runtime:
Route r = handler.getClass().getMethod("handle").getAnnotation(Route.class);
System.out.println(r.path()); // e.g. "/users"@Target: Restricting Application Points
@Target uses ElementType constants to restrict where the annotation can appear. An error at compile time if applied to a disallowed element.
import static java.lang.annotation.ElementType.*;
@Target({METHOD, CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
public @interface Measured {}All ElementType Values
Full list: TYPE (class/interface/enum), FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_PARAMETER (generic type param), TYPE_USE (any type usage).
// TYPE_USE: annotate any type reference
@NotNull String name;
List<@NonNull String> items;
public @Valid User createUser(@NotNull String name) { ... }TYPE vs TYPE_USE
TYPE targets class/interface/enum declarations. TYPE_USE (Java 8+) targets any use of a type including generics, casts, and extends clauses — enabling type-level null-safety annotations.
@Target(ElementType.TYPE_USE)
@interface NonNull {}
// Can be applied to:
List<@NonNull String> list;
@NonNull String result = (@NonNull String) obj;Combining Target and Retention
Most useful framework annotations combine RUNTIME retention with specific targets. Example: a validation annotation on fields only.
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Range {
int min() default 0;
int max() default Integer.MAX_VALUE;
}Inheriting Annotations with @Inherited
@Inherited is a meta-annotation that causes class-level annotations to be inherited by subclasses. It has no effect on method or field annotations.
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Framework {}
@Framework class Base {}
class Child extends Base {} // @Framework visible on Child too@Documented: Javadoc Inclusion
Apply @Documented so the annotation appears in the generated Javadoc for annotated elements. Without it, annotations are invisible in the API documentation.
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Auditable {
String description() default "";
}Reading Retention Info at Runtime
You can inspect the retention of an annotation type itself using getAnnotation(Retention.class) on the annotation class object.
Retention r = Retry.class.getAnnotation(Retention.class);
System.out.println(r.value()); // RUNTIME, CLASS, or SOURCEQuick Check
Which ElementType covers class, interface, and enum declarations?
Recap
Use SOURCE for compile-time tools, CLASS for bytecode analysis, RUNTIME for reflective frameworks. Restrict with @Target to prevent misuse. Add @Documented for API annotations and @Inherited for class-hierarchy annotations.
Frequently asked questions
Is the “Retention Policies and Target Types” lesson free?
Yes — the full text of “Retention Policies and Target Types” is free to read here on the web, and the Java Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Java Academy course, upgrade to CoddyKit PRO.
What will I learn in “Retention Policies and Target Types”?
Choose SOURCE, CLASS, or RUNTIME retention and restrict target elements with @Target. You practise Java Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Java Academy?
No prior experience is required. Java Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Retention Policies and Target Types” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Java Academy lesson?
Yes. Every Java Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Defining Annotations: Elements and Defaults
- Retention Policies and Target Types
- Runtime Annotation Processing
- Compile-Time Annotation Processors