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