Annotations

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. @interface Hints {
  2. Hint[] value();
  3. }
  4. @Repeatable(Hints.class)
  5. @interface Hint {
  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. class Person {}

Variant 2: Using repeatable annotations (new school)

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

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. @interface MyAnnotation {}