Repeating Annotations in Java 8 are introduced for the support of having multiple same annotations to a declaration. Before Java 8 duplication annotations are not allowed.

Let’s take a use case of having a class Products which has variables with names of products and we want to attach annotations to define the names of countries where the product is manufactured. Prior to Java 8, since we don’t have support for multiple same annotations on the same declaration or type case, we create two different annotations and place on products variable as below.

Example:

  1. Country1.java
    Country1.java
    public @interface Country1 {
        String name() default "";
    }
  2. Country2.java
    Country2.java
    public @interface Country2 {
        String name() default "";
    }
  3. Products.java
    Products.java
    public class Products {
        @Country1(name = "India")
        @Country2(name = "China")
        private String footBall;
    }

Repeating Annotations in Java 8

Java 8 has introduced an annotation type called java.lang.annotation.Repeatable for annotating another annotation to inform the compiler that this annotation is Repeatable. This gives the developer flexibility to have multiple same annotations on a variable.

Repeating Annotations

Usage:

  1. Repeatable Annotation: The Repeating Annotation has to be annotated with @Repeatable to have the capability to repeat. We have to pass the class name as a parameter to the meta-annotation @Repeatable where the compiler can store all the multiple annotations and that acts as a container for values.
    1. Example: Country.java
      Country.java
      import java.lang.annotation.Repeatable;
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      
      @Retention(RetentionPolicy.RUNTIME)
      @Repeatable(value = Countries.class)
      public @interface Country {
          String name();
      }
  2. Container Annotation: The container annotation can be declared as normal annotation and it has to have a value variable whose type is an array of above Repeatable annotation.
    1. Example: Countries.java
      Countries.java
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      
      @Retention(RetentionPolicy.RUNTIME)
      public @interface Countries {
          Country[] value() default {};
      }
  3. Implementation: Now the products class can define the same annotation multiple times on a single product.
    1. Example: Products.
      Products.java
      public class Products {
          @Country(name = "India")
          @Country(name = "China")
          private String volleyBall;
      }
  4. Retrieving Annotations: We can retrieve annotation data by using Reflection API. getAnnotationsByType() is used to retrieve the annotation values. We can also use getAnnotation() method passing the Container Annotation class as input to it to retrieve the values.
    RepeatingAnnotationsTest.java
    import java.lang.reflect.Field;
    
    public class RepeatingAnnotationsTest {
    
        public static void main(String[] args) throws NoSuchFieldException,
                SecurityException {
            Products products = new Products();
            Class<?> c = products.getClass();
            Field fd = c.getDeclaredField("volleyBall");
            Country[] countries = fd.getAnnotationsByType(Country.class);
            for (Country country : countries) {
                System.out.println(country.name());
            }
        }
    }

Conclusion:

Though Repeating Annotations is a small addition to Java 8, it is a very useful change released in Annotation category, when all advanced frameworks configuration is moving towards annotation-based system from XML.

Happy Learning 🙂