Repeating annotations in Java 8

In Java 7 and before attaching more than one annotation of the same type to the same part of the code (e.g. a class or a method) was forbidden. Therefore, the developers had to group them together into single container annotation as a workaround:

@Authors({
    @Author(name = "John"),
    @Author(name = "George")
})
public class Book { ... }

Java 8 brought a small yet very useful improvement called repeating annotations which allows us to rewrite the same code without explicitly using the container annotation:

@Author(name = "John")
@Author(name = "George")
public class Book { ... }

For compatibility reasons, the container annotation is still used but this time the Java compiler is responsible for wrapping the repeating annotations into a container annotation.

Declaring repeatable annotation type

User-defined annotations are not repeatable by default and have to be annotated with @Repeatable annotation:

package com.example.customannotation;

import java.lang.annotation.Repeatable;

@Repeatable(value = Authors.class)
public @interface Author {
    String name() default "";
}

The element value of @Repeatable annotation represents the type of the container annotation:

package com.example.customannotation;

public @interface Authors {
    Author[] value();
}

When repeating annotation Author is used multiple times on the same part of the code, the Java compiler automatically creates container annotation Authors and stores all repeating annotations Author into its value element.

This is the minimal working configuration but in most cases you may decide to additionally specify at least target and retention of the annotation type.

Accessing annotations via reflection

Repeating annotations can be accessed in two ways. The first one is to access them by first getting their container annotation using getAnnotation() or getDeclaredAnnotation() methods of AnnotatedElement interface:

Authors authors = klazz.getAnnotation(Authors.class);
for (Author author : authors.value())
    System.out.println("Author=" + author.name());

The second method relies on newly introduced getAnnotationsByType() and/or getDeclaredAnnotationsByType() methods which automatically scan though the container annotation, extract the repeating annotations and return them at once as an array:

Author[] authors = klazz.getAnnotationsByType(Author.class);
for (Author author : authors)
    System.out.println("Author=" + author.name());

Conclusion

Repeating annotations is a small addition to Java which simplifies usage of some annotations in various frameworks (especially in Hibernate and JPA). Because the feature is quite new, you may still need to explicitly use container annotation for some time (until @Repeatable is added to all necessary annotation types).

Advertisement

About Robert Piasecki

Husband and father, Java software developer, Linux and open-source fan.
This entry was posted in Java and tagged . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.