A simpler model for repeating annotations
Ali Ebrahimi
ali.ebrahimi1781 at gmail.com
Tue Jan 8 03:17:31 PST 2013
Hi Alex,
I think, I'm late to list.
The following is just my 2 cent suggestion to your proposal.
1) Introduce AnnotationContainer annotation in java.lang package (java se 8
) as default container for repeating annotations:
@interface AnnotationContainer{ Annotation[] value(); }
(relax rules of jls 9.6.1 to include Annotation (class) type)
2) Modify Repeatable annotation:
@interface Repeatable{ Class<? extends Annotation> value() default
AnnotationContainer.class; }
with 1, 2 in mind we have one standard default container annotation for all
repeating annotations that don't specify containing annotation. This allows
to package all repeating annotations in one container annotation and reduce
static and dynamic footprint. In other side, developer don't need to
introduce one containing annotation for each repeating annotations, this
also reduce number of class files and makes this feature of java 8 user
friendly for developer. developer just need annotate repeating annotations
with Repeatable annotation.
example:
@Repeatable
@interface Foo { int value(); }
@Repeatable
@interface Bar{}
@Repeatable(AliContainer.class)
@interface Ali{ String value();}
@interface AliContainer{ Ali[] value(); }
@Foo(1) @Foo(2) @Bar @Bar @Ali("java lover") @Ali("Flying on the Clouds")
class A {}
in class file:
@AnnotationContainer({@Foo(1), @Foo(2), @Bar, @Bar})
@AliContainer({@Ali("java lover"), at Ali("Flying on the Clouds")})
class A {}
Regards,
Ali Ebrahimi
On Sat, Dec 29, 2012 at 12:47 AM, Alex Buckley <alex.buckley at oracle.com>wrote:
> Feedback from Java EE architects indicates a strong preference for 100%
> behavioral compatibility for legacy core reflection methods.
>
> Summarizing Mike Keith's comments: 1) getAnnotation(Class) must not return
> one @Foo annotation if multiple @Foo annotations were present in source,
> and 2) getAnnotations() must not return multiple @Foo annotations if they
> present in source.
>
> These requirements imply keeping containment at the heart of
> repeatability. Why? Assume there were no containers, and you could simply
> write:
>
> @Repeatable @interface Foo {}
>
> such that @Foo @Foo on class A is compiled directly into A.class. This
> scheme would impose high complexity on legacy core reflection methods.
> getAnnotation(Foo.class) would have to read _all_ annotations (declared and
> inherited) to detect multiple @Foo annotations then return null or throw an
> exception. (Remember, returning one of the multiple annotations is
> "wrong".) getAnnotations() would have similar trouble deciding what to
> return if multiple @Foo annotations are found. In essence, the legacy core
> reflection methods are morally incompatible with uncontained multiple
> annotations. The solution is to compile multiple annotations with
> containers, and have the legacy core reflection methods behave identically
> to Java SE 7 (no look through).
>
> To support new reflective clients who understand repeating annotations, we
> can keep the previously-proposed getAnnotations(Class) which looks through
> containers. That is, getAnnotations(Foo.class) returns @Foo @Foo because it
> a) detects that Foo.class is a repeatable annotation type with a containing
> annotation type of FooContainer, then b) looks through any @FooContainer
> present.
>
> It is clear that a repeatable annotation type must still nominate its
> containing annotation type, but the reverse is no longer true. That is, the
> declaration of FooContainer no longer needs to say
> @ContainerFor(Foo.class). This is a direct consequence of dropping look
> through for the legacy core reflection methods. Also, the difficult
> question about calling getAnnotations() on a subclass - should it look
> through an inherited container, or return it? - goes away, as normal
> overriding policy gives good answers.
>
> Here's a simple model that Joe, Joel, and I are happy with:
>
> - @Repeatable(FooContainer.**class) on @interface Foo {} causes
> @Foo @Foo in source to be containerized in the class file.
> (Rename @ContainedBy to @Repeatable.)
>
> - The rules for a well-formed relationship between Foo and
> FooContainer remain.
>
> - Core reflection's legacy methods return what's in the class file:
> - get[Declared]Annotation(Foo.**class) returns nothing, like today.
> - get[Declared]Annotations() returns @FooContainer, like today.
>
> - Core reflection's new typed methods look through containers:
> - get[Declared]Annotations(Foo.**class) returns @Foo @Foo.
>
> - An annotation writer may manually rewrite @FooContainer(...) as
> @Foo @Foo, and it will be containerized with perfect compatibility.
>
> - Language model's legacy methods follow core reflection:
> - Element.getAnnotation(Foo.**class) returns nothing, like today.
> - Element[s].get[All]**AnnotationMirrors() returns @FooContainer, like
> today
>
> - Language model's new typed method looks through:
> - Element.getAnnotations(Foo.**class) returns @Foo @Foo.
> - We may add Element.getAnnotationMirrors(**TypeElement) in future.
>
> I think the reduced semantic burden for an annotation type owner (no more
> @ContainedFor) and the stronger compatibility story for an annotation
> reader (no look through for legacy methods) are real improvements. We will
> specify and implement the model over the next month.
>
> Alex
>
More information about the enhanced-metadata-spec-discuss
mailing list