Do repeating annotations need a public container?

662 views Asked by At

I noticed a discrepancy between Eclipse's compiler and javac while using repeating annotations. The repeating annotation and its container were in the same package, but the former was declared public, while the latter remained package-private. Eclipse had no problem with the arrangement, even though the repeating annotation was referenced in another package. javac, on the other hand, refused to compile, saying

value() in [container] is defined in an inaccessible class or interface

My question is, which one is correct? I couldn't find any rule about this in the JLS. Does that mean it's open to interpretation? Or is there a bug in one of the compilers?

1

There are 1 answers

0
Holger On BEST ANSWER

There is no statement regarding accessibility but the specification makes it clear that it is possible that a repeatable annotation may be restricted to be repeatable at certain locations only, due to the way how the containing annotation has been declared.

JLS §9.6.3

  1. T is applicable to at least the same kinds of program element as TC (§9.6.4.1). Specifically, if the kinds of program element where T is applicable are denoted by the set m1, and the kinds of program element where TC is applicable are denoted by the set m2, then each kind in m2 must occur in m1, …

    This clause implements the policy that an annotation type may be repeatable on only some of the kinds of program element where it is applicable

This is also backed with an example:

Example 9.6.3-2. Restricting Where Annotations May Repeat

An annotation whose type declaration indicates a target of java.lang.annotation.ElementType.TYPE can appear in at least as many locations as an annotation whose type declaration indicates a target of java.lang.annotation.ElementType.ANNOTATION_TYPE. For example, given the following declarations of repeatable and containing annotation types:

@Target(ElementType.TYPE)
@Repeatable(FooContainer.class)
@interface Foo {}

@Target(ElementType.ANNOTATION_TYPE)
@Interface FooContainer {
    Foo[] value();
}

@Foo can appear on any type declaration while @FooContainer can appear on only annotation type declarations. Therefore, the following annotation type declaration is legal:

@Foo @Foo
@interface X {}

while the following interface declaration is illegal:

@Foo @Foo
interface X {}

While this is discussing restrictions imposed by @Target rather than accessibility modifiers, it describes a “spirit” that can be applied to the latter as well. The intention clearly seems to be that a repeatable annotation can only be repeated if the properties of the specified container annotation allow it, otherwise the annotation still may be used, but only with a single occurrence.

It’s not like the properties of a repeatable annotation were capable of overriding the properties of the container annotation type. This is in line with the behavior at all other places; even if there is no reference to the inaccessible annotation type in the source code, compiling the repeated annotation would create a reference in the class file and a class file may not contain symbolic references to inaccessible classes and there shouldn’t be an exception only for container annotations.