Initial spec for Repeating Annotations and Method Parameter Reflection

Alex Buckley alex.buckley at oracle.com
Tue Aug 21 09:57:25 PDT 2012


Hi Remi,

On 8/21/2012 6:57 AM, Rémi Forax wrote:
> I've just read the chapter 1, there is a small bug in the draft,
> section 9.6.3.8 (page 6 of the draft), ContainedBy is spelled
> ContainerAnnotation in the java code provided.

The code reflects an earlier internal draft and will be updated.

> In section Reflection, you forget to talk about the behavoir of
> isAnnotationPresent(), even if there is no big deal.

Didn't forget. Small details like this will be tidied up as the feature
progresses.

> Now, I don't see why @ContainerFor is needed, given that the
> compiler and the reflection runtime can use already existing
> information (the return type of value()) to reconstruct the
> information given by @ContainerFor.

Initially we didn't have @ContainerFor, and thought it would be possible
to "infer" that an annotation T is a "container" by checking that its
value() element's return type T' is indeed an annotation type which
expects to be contained by T. A small matter of programming, as some
might say. However, for compatibility reasons, this turned out to be
insufficient. Here's the reasoning:

A marker annotation is needed because lines (1) and (2) below compile to
the same ClassFile structure, yet the reflective API which operates on
that structure needs to determine whether the repetition was implicit
(1) or explicit (2) in order to give results that satisfy legacy
consumers.

(1) @Foo(1) @Foo(2) class A {}
(2) @FooContainer({@Foo(1), @Foo(2)}) class A {}

- If the source was (1), then
A.class.get[Declared]Annotation(Foo.class) should "look through" the
synthesized container and return @Foo(1). In particular, if the source
was initially annotated with just @Foo(1), then adding @Foo(2) should
not change the result from @Foo(1) to null (because the @Foo's were
wrapped in a @FooContainer). The act of repeating an annotation is
source-compatible, and a source-compatible change in code should not
imply a behavior-incompatible change for reflective code.

- If the source was (2), then
A.class.get[Declared]Annotation(Foo.class) should _not_ look through
@FooContainer (since it was written by hand in legacy code) and should
return null (since there are logically no @Foo's on class A in (2)).

You can see that it's not always desirable to "look through" an 
annotation which "appears" to be a container based on its value() 
element. The explicit @ContainerFor seems like a useful and reasonable 
piece of documentation.

Alex



More information about the enhanced-metadata-spec-discuss mailing list