dev@glassfish.java.net

Re: JDK6 and meaning of _at_Override

From: Ken Cavanaugh <Ken.Cavanaugh_at_Sun.COM>
Date: Fri, 24 Oct 2008 09:36:09 -0700
Lloyd Chambers wrote:
Thanks everyone for the very interesting followup!

I've read the posts, etc, but it's still unclear to me whether @Override is legal or not on a sub-interface (in JDK 1.6). My original intent was to have the compiler enforce the claim: "This method MUST exist in a super-interface".

Implementation doesn't matter for my intended purpose.

- Every @Configured that is a PropertyBag needs to redeclare the getProperty() method so it can add annnotations to it;
- No @Configured should have the getProperty() method unless it IS_A PropertyBag.

We have this case not just for PropertyBag, but for several other interfaces as well eg (Named).

======== Annnotations and interface hierarchies ==========

What does it mean to have an interface hierarchy with successive re-declarations of the same method?
Good question.  I've done a lot a annotation processing lately, mainly for JMXA.  The first thing to remember
is that any AnnotatedElement has at most one instance of any annotation (because AnnotatedElement.getAnnotation
can only return one annotation of any type, mirroring the fact that multiple declarations of the same
annotation on the same element are rejected by the compiler).  getAnnotation will return the value of the annotation on
the element on which it is called, if present.  For classes, if the annotation definition contains the @Inherited
meta-annotation, getAnnotation will return the first instance of the annotation found in following the superclass
inheritance chain.  Interface inheritance has NO effect on this (see the javadoc for java.lang.annotation.Inherited),
and this can definitely be a problem.

For my own purposes (since I want to see annotations on interfaces as well as classes), I wrote some simple utilities
to represent the class and interface inheritance as a graph, and then use a reversed post-order traversal of the
graph to determine the search order when looking for annotations.  That way I can see annotations on interfaces
as well as classes.
-- Do the annotations accumulate when programs go to use them? (Depends on how the API is used I think)
No, but you can find all of them by exploring the class hierarchy if needed (or yes, you can write code that
effectively accumulates annotations if you wish, depending on how you view my answer :-)).
-- Only one annotation of a given type is possible on each target in a given class/interface.  But sub-interfaces can add another annotation of the same type.  How does this interact with the API, and what is it supposed to mean for a system like HK2?
It completely depends on the implementation.  The most straightforward case is to just call getAnnotation on the class,
in which case (for inherited annotations) you walk up the superclass chain until you get an annotation, or end at Object.
But any implementation is free (as in my case) to do whatever it wants to.  That's why the @Inherited meta-annotation is
not so useful: it really means NOTHING outside of the context of a particular implementation of annotation processing.

I can see two useful models here:
There are probably other models that I haven't thought of that make sense.

Example:  (http://en.wikipedia.org/wiki/Lichen)

How many @GrowableStuff annotations exist on Lichen?
How many @Override annotations?
And is this legal in JDK 6 or not?
Not sure about @Override, it sounds like (from other discussions) that it is legal in JDK 6 (but not in JDK 5).
The other annotations should be legal in any case.

public interface Growable {
@GrowableStuff(...)  public void grow();
}

public interface Mycobiont extends Growable {
@Override @GrowableStuff(...) @MycobiontStuff public void grow();
}

public interface Phycobiont extends Growable {
@Override @GrowableStuff(...) @PhycobiontStuff  public void grow();
}

public interface Lichen extends Mycobiont, Phycobiont {
@Override @GrowableStuff(...) @LichenStuff public void grow();
}
What I THINK will happen for the methods (I need to check this, it's important for JMXA as well)
is that you will get the annotations on the Method object for the method as defined in a
particular class.  In your example,

Lichen.class.getDeclaredMethod( "grow" ).getAnnotations()

should return the @GrowableStuff(...) and @LichenStuff annotations (@Override is annotated
with source retention, so the compiler will discard it).

On the other hand,

Phycobiont.class.getDeclaratedMethod( "grow" ).getAnnotations()

should return @GrowableStuff( ... ) (with different info than on Lichen) and @PhycobiontStuff.

Ken.