Annotations in Java 8 are repeatable. Let’s dive directly into an example to figure that out.

First, we define a wrapper annotation which holds an array of the actual annotations:

  1. @interfaceHints{
  2. Hint[] value();
  3. }
  4. @Repeatable(Hints.class)
  5. @interfaceHint{
  6. String value();
  7. }

Java 8 enables us to use multiple annotations of the same type by declaring the annotation @Repeatable.

Variant 1: Using the container annotation (old school)

  1. @Hints({@Hint("hint1"),@Hint("hint2")})
  2. classPerson{}

Variant 2: Using repeatable annotations (new school)

  1. @Hint("hint1")
  2. @Hint("hint2")
  3. classPerson{}

Using variant 2 the java compiler implicitly sets up the @Hints annotation under the hood. That’s important for reading annotation information via reflection.

  1. Hint hint =Person.class.getAnnotation(Hint.class);
  2. System.out.println(hint);// null
  3. Hints hints1 =Person.class.getAnnotation(Hints.class);
  4. System.out.println(hints1.value().length);// 2
  5. Hint[] hints2 =Person.class.getAnnotationsByType(Hint.class);
  6. System.out.println(hints2.length);// 2

Although we never declared the @Hints annotation on the Person class, it’s still readable via getAnnotation(Hints.class). However, the more convenient method is getAnnotationsByType which grants direct access to all annotated @Hint annotations.

Furthermore the usage of annotations in Java 8 is expanded to two new targets:

  1. @Target({ElementType.TYPE_PARAMETER,ElementType.TYPE_USE})
  2. @interfaceMyAnnotation{}