Java Annotation Retention Policies
Annotation retention policies determine how long annotation metadata is preserved: only in source code, in compiled class files, or through runtime. In Java, the `@Retention` annotation selects among `SOURCE`, `CLASS`, and `RUNTIME`.
Java defines three retention policies through `java.lang.annotation.RetentionPolicy`. `SOURCE` annotations are available to the compiler while processing source code but are not stored in the resulting class file.
`CLASS` is the default retention policy when an annotation declaration does not specify another policy. The annotation is recorded in the compiled `.class` file, but ordinary runtime reflection does not make it available as a runtime annotation.
`RUNTIME` annotations are retained in the class file and made available to reflection while the annotated class, method, field, or other supported element is loaded. Frameworks commonly use this policy when they need to inspect annotations at runtime.
The choice should match when the metadata is needed. Compile-time tools generally use `SOURCE`, metadata needed by bytecode-oriented tools can use `CLASS`, and reflection-based frameworks require `RUNTIME`. Retention is independent of where an annotation is allowed to appear; that concern is controlled by `@Target`.
Key points
- `SOURCE` metadata is discarded before the class file is produced.
- `CLASS` metadata is stored in bytecode and is the default retention policy.
- `RUNTIME` metadata can be discovered through Java reflection.
- `@Retention` controls lifetime; `@Target` controls applicable program elements.
- Reflection-based processing normally requires `RUNTIME` retention.
Interview questions
What are the three Java annotation retention policies?
The three policies are `SOURCE`, `CLASS`, and `RUNTIME`. `SOURCE` keeps an annotation only during source processing. `CLASS` stores it in the compiled class file and is the default. `RUNTIME` also makes it available through reflection.
What happens if an annotation declaration does not specify `@Retention`?
Its retention policy is `CLASS`. That means the annotation is included in the generated class file. It is not consequently available as a runtime annotation through normal reflection.
Why would you choose RUNTIME retention for an annotation?
You choose `RUNTIME` when application code or a framework needs to inspect the annotation after compilation. Java reflection can then query the annotation on supported runtime elements. This is common for dependency injection, configuration, validation, and other reflection-based mechanisms. If the information is only needed during compilation, runtime retention is unnecessary.
How is annotation retention different from annotation target?
Retention answers when annotation metadata remains available. Target answers where the annotation can legally be applied, such as a class, method, field, or parameter. They solve different problems and can be specified independently on an annotation declaration. For example, an annotation can target methods while also having `RUNTIME` retention.
A framework cannot find a custom annotation with reflection. What should you check first?
First, inspect the annotation declaration and verify that it has `@Retention(RetentionPolicy.RUNTIME)`. If it uses `SOURCE` or `CLASS`, normal runtime reflection will not expose it as a runtime annotation. Next, verify that the annotation is actually placed on the element being inspected and that the framework is querying the correct reflective element. I would also check whether inheritance or annotation placement affects the particular reflection API being used.