Spec updates for repeating annotations (reflection)
Alex Buckley
alex.buckley at oracle.com
Fri Dec 7 13:59:10 PST 2012
I have added further examples in section 1.2 (core reflection) to cover
what I believe to be all critical combinations of base annotations and
container annotations under inheritance.
Example 1.2-5 is interesting because it raises the question of whether
getAnnotations() should expose an inherited container annotation when
its containerized base annotations are overridden. Let's break it down:
- With no container annotation inheritance, things are simple:
1.2-3:
@Foo(0) @FooContainer({@Foo(1), at Foo(2)}) class A {}
A.class.getAnnotations() = [ @Foo(0), @Foo(1), @Foo(2) ]
1.2-4:
@Foo(0) class A {}
@FooContainer({@Foo(1), at Foo(2)}) class B extends A {}
B.class.getAnnotations() = [ @Foo(1), @Foo(2) ]
- With container annotation inheritance + overriding, things are not simple:
1.2-5:
@FooContainer({@Foo(1), at Foo(2)}) class A {}
@Foo(0) class B extends A {}
B.class.getAnnotations() = [ @Foo(0) /* and @FooContainer(..)? */ ]
I tend to think that container annotations should be invisible unless
requested explicitly via get[Declared]Annotation[s](FooContainer.class).
Consequently, in 1.2-5, I do not show @FooContainer(..) being returned
by getAnnotations() after Foo has become repeatable with FooContainer.
Comments welcome.
Alex
On 12/6/2012 12:01 PM, Alex Buckley wrote:
> I have updated section 1.3 of the spec as proposed below.
>
> I have also 1) added remarks at the start of chapter 1 to explain the
> design, and 2) added examples in section 1.2 (core reflection) to cover
> more scenarios.
>
> The spec is at http://cr.openjdk.java.net/~abuckley/8misc.pdf as usual.
>
> Alex
>
> On 12/5/2012 2:46 PM, Alex Buckley wrote:
>> We discovered two small issues with section 1.3 of the spec:
>>
>>
>> 1. The spec proposes a new method, Element.getAnnotations().
>>
>> This method is proposed for consistency with
>> AnnotatedElement.getAnnotations(), but it turns out to be difficult to
>> implement in the context of the language model. The problem is that, at
>> compile-time, there might not be instances of Class objects for the
>> annotations we try to look at. The other new methods -
>> Element.getAnnotation[s](Class<T>) - do not have this issue since their
>> callers must supply a Class object.
>>
>> It would be possible for Element.getAnnotations() to throw exceptions if
>> necessary Class objects were not found, but there is no good unchecked
>> exception type available in the language model API. It would also be
>> possible to skip over annotations for which Class objects are
>> unavailable, and return incomplete results, but this seems undesirable.
>>
>> I propose to drop the method. Essentially, it's fine in core reflection
>> but too brittle for the language model.
>>
>>
>> 2. The spec proposes to refine Element.getAnnotationMirrors() and
>> Elements.getAllAnnotationMirrors().
>>
>> If the language model API only has a class file available for the
>> element on which annotation mirrors are requested, then the API cannot
>> be sure that it's right to "look through" @FooContainer (if directly
>> present on the element) and return @Foo mirrors.
>>
>> This is true even if FooContainer is a well-formed containing annotation
>> type available to the API. The source code of the element - which the
>> API strives to reflect - could literally have said @FooContainer(...).
>> Unfortunately, a compiler has no way to mark a container annotation as
>> "synthesized" during class file generation.
>>
>> It would be possible to adopt a policy of always looking through
>> container annotations on an element. This requires the language model
>> API to recognize container annotations, which in turn requires loading
>> the annotation's class file, which might not always be available.
>>
>> I propose to adopt this policy, while allowing the methods to sometimes
>> expose container annotations even if not present in source code.
>>
>>
>> Alex
More information about the enhanced-metadata-spec-discuss
mailing list