Java - Understanding Annotation RetentionPolicy Enums

This article explains the differences between Java's RetentionType enums used on annotations.

If you look at the source code of annotations, it's very common to see a @Retention annotation. The value passed to the @Retention annotation is a RetentionPolicy enum. What are the differences of the enum values? Find out in this article.

RetentionPolicy.SOURCE

If this enum is used, the annotation will be discarded by the compiler. After the code has been compiled, the annotation is not useful anymore and therefore it's not written to the bytecode.

For example, there is an annotation whose retention policy is SOURCE.

  @Retention(RetentionPolicy.SOURCE)
  @Target(ElementType.TYPE)
  public @interface MySourceAnnotation {
  
    String value() default "";
  }

If a class named MyBean uses the annotation and you open the generated .class file, you will not find the annotation.

If you get the annotation list of the class using getAnnotations (e.g. MyBean.class.getAnnotations()), you will not find MySourceAnnotation.

Some annotations that use this retention type are @Override and @SuppressWarnings.

RetentionPolicy.CLASS

This is the default type. If an annotation uses this type, it means the annotation is recorded in the file, but it will not be retained at the run time by the VM.

For example, there is an annotation whose retention policy is CLASS.

  @Retention(RetentionPolicy.CLASS)
  @Target(ElementType.TYPE)
  public @interface MyClassAnnotation {
  
    String value() default "";
  }

If a class named MyBean uses the annotation and you open the generated .class file, you'll find the annotation name preceded by RuntimeInvisibleAnnotations.

 
 RuntimeInvisibleAnnotations...com/woolha/example/annotations/MyClassAnnotation

If you get the annotation list of the class using getAnnotations (e.g. MyBean.class.getAnnotations()), you will not find MyClassAnnotation.

Despite being the default type, it's not common to use it. It can be useful if you want to get the annotation by reading the bytecode programmatically. The GwtCompatible annotation of Google Guava library uses this retention type.

RetentionPolicy.RUNTIME

If this enum is used, the annotation is recorded in the class file and retained at the run time. In addition, you can get the annotation using reflection.

For example, there is an annotation whose retention policy is RUNTIME.

  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public @interface MyRuntimeAnnotation {
  
    String value() default "";
  }

If a class named MyBean uses the annotation and you open the generated .class file, you'll find the annotation name preceded by RuntimeVisibleAnnotations.

 
 RuntimeVisibleAnnotations...com/woolha/example/annotations/MyRuntimeAnnotation

If you get the annotation list of the class using getAnnotations (e.g. MyBean.class.getAnnotations()), you will find MyRuntimeAnnotation.

The @Deprecated annotation uses this retention type.

Summary

The retention type affects whether an annotation is recorded in the class file and retained at the run time. Having understood the difference between those types, you should choose the correct one if you create a custom annotation.