Behavior of getAnnotationsByType for @FooContainer({})

Alex Buckley alex.buckley at oracle.com
Mon Oct 14 12:09:35 PDT 2013


On 10/14/2013 5:44 AM, Andreas Lundblad wrote:
> I agree that making containers as "transparent" as possible is a good
> idea. In this case however, I would argue that we should see through the
> container, but not through the empty list.
>
> Take for instance the case where idiomatic containers are used, i.e. we
> have
>
> @FooContainer({@Foo}) class A {}
> @FooContainer({}) class B extends A {}
>
> Here {} is bound to overwrite {@Foo}. If we say that @FooContainer({})
> should be "ignored" (i.e. its presense should not prevent inheritence)
> some SE7 code may have troubles adopting the @Repeatable feature. If we,
> on the other hand, do take the empty list into consideration, the
> indirectly present annotations can still be inherited by simply leaving
> @FooContainer({}) out.

SE 7 code running on SE 8, or even recompiled on SE 8, sees no change. 
The way it "adopts" the @Repeatable feature is to start using 
get[Declared]AnnotationsByType, whose behavior is clearly documented. 
Whether code that starts using B.class.getAnnotationsByType(Foo.class) 
is "surprised" to see @Foo on B depends on the "search policy" inherent 
in the code, that is, the way it looks for annotations in the class 
hierarchy.

For example, suppose SE 7 code calls B.class.getAnnotations(), sees 
@FooContainer({}) with its empty list, and determines there are no @Foo 
annotations on B. That's a reasonable search policy. Now, what if the 
author of A realizes there is no point using a container for only one 
@Foo, and rewrites A so only @Foo appears? Answer: the SE 7 code now 
sees @Foo on B as well as @FooContainer({}), and can presumably cope by 
simply using the @Foo. (We determined in 2012 that SE 7 code in 
frameworks can handle a base annotation side by side with a container 
annotation; ultimately, one expects a framework to use the @Foo rather 
than throw it away because of the {}. After all, the SE 7 code used 
getAnnotations() so is aware that superclasses can contribute @Foo's to 
the party.) When the SE 7 code migrates to SE 8 by using 
B.class.getAnnotationsByType(Foo.class), it will still see @Foo, so 
that's fine.

If the search policy all along had been to call 
B.class.getDeclaredAnnotations(), then the SE 7 code would never have 
seen @Foo on B, regardless of the annotations on A. Migrating to 
B.class.getDeclaredAnnotationsByType(Foo.class) will still not expose 
@Foo on B, so that's fine.

Bottom line, our long-term goal is to move people away from writing 
container annotations by hand, so embedding special treatment for 
"empty" container annotations into the new core reflection methods is 
undesirable. We have a simple model that works pretty well, and it's 
past time for changing it.

Alex


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