Initial spec for Repeating Annotations and Method Parameter Reflection

Rémi Forax forax at univ-mlv.fr
Tue Aug 21 11:53:34 PDT 2012


On 08/21/2012 06:57 PM, Alex Buckley wrote:
> 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.

i know, i know :)

>
>> 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.

I think the following assumption is broken,
[with get[Declared]Annotation(Foo.class)]
"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"

It should be true with get[Declared]Annotations (with an 's' at the end) 
not with get[Declared]Annotation,
it's not a good idea to choose between the two Foo, because annotations 
are like modifiers,
@Foo(1) @Foo(2) should be equivalent to @Foo(2) @Foo(1). And here, you 
clearly break that rule.

So know that adding a repeated annotation can only be a source 
compatible change if users use get[Declared]Annotations(), @ContainerFor 
is not needed anymore :)

>
> Alex

Rémi




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