JEP 120: Repeating Annotations

Jesse Glick jesse.glick at
Fri Jan 6 09:48:28 PST 2012

On 01/05/2012 06:32 PM, Joe Darcy wrote:
> other consumers of class files don't have to have extensive modifications.

If there are other class file parsers which assume (contrary to the current JVM spec!) that only one annotation of a given type is present on a given element, they would 
need to be fixed - e.g. using a list or multimap rather than a map, or simply ignoring second and subsequent occurrences if irrelevant for their use case. This does not 
feel like "extensive modifications", especially if compared to other likely class file changes such as for lambdas, but it is true that it is a change when compared to 
JDK 7 (at least when restricted to class files produced by javac).

> any solution to repeating annotations that did not acknowledge and leverage this situation is unlikely to have speedy adoption.

Well assuming that the code which reads the annotation (elt.getAnnotation(Thing.class)) is in the same overall source project as the definition of the annotation itself 
(, which is typical, and assuming that this feature is targeted for JDK 8, there are several cases:

1. The defining/consuming code is using JDK 5, 6, or 7 as a baseline. Then it cannot use either @Repeatable or @Container (these would not even be available to compile 
against), so cannot be changed at all, even if the annotating code (@Things({...}) class C {}) is happy with assuming JDK 8+.

2. The def/cons code compiles against JDK 8 but uses -source/-target 5-7 and uses e.g. animal-sniffer to avoid unintentional use of JDK 8+ APIs. Probably it could add 
@Rep/@Cont to the annotation definition, assuming nothing inside this project is itself annotated. Other annotating code could use @Thing @Thing if using JDK 8+, but 
would still have to use @Things if retaining 5-7 compatibility. The consuming code in the case of @Cont looks for both @Thing and @Things as in #1; in the case of @Rep it 
looks for @Things and/or repeated @Thing (filtering elt.getAnnotations() rather than elt.getAnnotation(Thing.class)) - a few extra lines of code.

3. The def/cons code uses JDK 8 as a baseline, and annotating code does too. In the case of @Cont, @Things still has to be defined, and the consuming code still has to 
look for @Thing and/or @Things; in the case of @Rep, the consuming code just looks for repeated @Thing, as there is no @Things.

4. @Things was added to the API when using 5-7 as a baseline, but 8 is now the new baseline. In the case of @Cont, the annotation is added and the consuming code is 
probably the same (TBD whether it still has to check for elt.getAnnotation(Thing.class) if there is just one). In the case of @Rep, @Things is @Deprecated but still 
checked for in addition to repeated @Thing.

#1 is the normal case for the next several years. #3 is the normal case in the long run. #2 would probably be unusual; #4 is likely to be common for a few years.

In no case is the situation much different for the widespread annotating code, except that in case #3 the API user sees smaller and simpler Javadoc (also in case #4 if 
-nodeprecated is used). For the much rarer consuming code, there is no difference in case #1, @Cont is slightly easier in case #2 and #4, and @Rep is slightly easier in 
case #3.

More information about the compiler-dev mailing list