Search code examples
javaannotationsjava-8javac

Using @Repeatable while mainaining support for Java 7


Java 8 came with support for repeatable annotations through the use of "container" annotations:

@Repeatable(FooContainer.class)
@interface Foo {
    String value();
}
@interface FooContainer {
    Foo[] value();
}

@Foo("bar")
@Foo("baz")
public class SomeClass { }

I have a library where I want to support Java 7 (or newer). This library makes extensive use of annotations, and would greatly benefit from supporting repeatable annotations.

From what I understand, the container annotation works even in Java 7, only one would have to use this instead:

@FooContainer({@Foo("bar"),@Foo("baz")})
public class SomeClass { }

What I would ultimately like is: If the user of my library is using Java 8 the user will be able to use repeated annotation. If the user is using Java 7, he must stick to manually writing the container annotation.

Is something like this at all possible?


Solution

  • You need to provide two versions of your library:

    • one intended for use with Java 8, which meta-annotates the definition of Foo with @Repeatable.
    • one intended for use with Java 7, which explicitly defines both Foo and FooContainer.

    Unfortunately, you can't support both Java 7 and repeating annotations with one version of your library. If you want clients to be able to repeat the annotation, then Foo must be meta-annotated as @Repeatable. java.lang.annotation.Repeatable is defined only in Java 8. Therefore, if annotation Foo is meta-annotated as @Repeatable, both Foo and SomeClass can only be compiled and run on JDK 8 and above. (It can only be run on JDK 8 because when SomeClass is loaded, then Foo will be loaded, and any meta-annotation on Foo will be loaded.)