[JSR308] Suggestion (and example) for annotations that take any annotation or for annotation inheritance

Bill Pugh pugh at cs.umd.edu
Wed Oct 22 17:10:29 EDT 2008


On Oct 3, 2008, at 1:15 AM, Ciera Jaspan wrote:
> Hi everyone,
>
> I, and several others, have a need for either annotations that can  
> take any annotation or (preferably) for annotation inheritance.  
> While annotation inheritance is preferred, I understand there may be  
> good reasons this was left out of JSR-175 initially. If annotation  
> inheritance is not possible, having annotations which can take any  
> annotation would at least help. I've provided examples that motivate  
> each of these suggestions below, from a static analysis tool we are  
> building. Please let me know if you have any questions about the  
> examples given, or need further examples for motivation.



I proposed a solution for this a year ago on the 305 and 308 mailing  
lists, and I'll resurrect it again.

One of the design features of Java annotations is that there is no  
subtyping between annotations. I talked with Josh, and one of the  
things that would make changing this hard is methods such as the  
following in java.lang.reflect.Method:


T extends Annotation>
T
getAnnotation(Class<T> annotationClass)
           Returns this element's annotation for the specified type if  
such an annotation is present, else null.

This assumes that for any one place where an annotation could occur,  
and any particular annotation class, there is either zero or one  
instances of an annotation. This also means, for example, that you  
can't apply two difference instances of an annotation, with different  
parameters, to an annotation location. For example, you can't do:

@A(1) @A(2) int x;

Given this limitation, here is my proposed solution:

* Proposal 1: An annotation is allowed to extend/implement any number  
of interfaces.

  You might want to use this for marker interfaces, or define an  
interface that defines
  several elements/methods, and any annotation that implements that  
interface would be
  required to provide values for those methods.

  Note that the interface would just be a normal interface that could  
be implemented by
  classes as well.  interfaces can't define default values.

  This would allow you to define a standard set of element names that  
were used by
  by set of specific annotations, and allow internal API's that worked  
with any annotation
  from that set. You could also define an interface that was  
implemented both by annotations
  and by other, non-annotation based meta-data containers.

* Proposal 2 (requires proposal 1):

  An annotation can define an element that returns an interface that  
extends
  java.lang.annotation.Annotation. When applying such an annotation in  
the source code, the
  value used there must be some concrete annotation that extends that  
interface.

  Right now, the only values allowed for annotation elements are:
	primitives, String, Class, enums, specific annotation classes, and  
arrays

  This proposal would allow you to define annotations that, when  
applied in source code,
  accepted as an element value any one of a number of specific  
annotations. By defining the
  element to return a value of type Annotation, you can define an  
element where an arbitrary
  Annotation can be provided. For example, consider example where the  
Baz annotation can
  be applied with either a Foo or a Baz annotation as an element:

public interface AnnotationWithId extends Annotation {
  int id();
  }

public @interface Foo extends AnnotationWithId {
  int id();  // this could be omitted,
             // since it is defined in the interface
  String msg();
  }

public @interface Bar extends AnnotationWithId {
  int id() default 0; // couldn't be omitted,
                      // since the interface can't give a default value
  String date();
  }

public @interface Baz {
  AnnotationWithId annotation(); // can supply a @Foo or @Bar here
  String reason();
  }

public Test {
  @Baz(annotation=@Foo(id=17, msg="testing"), reason="because")
     public int test() { return 17; }
  }


Bill Pugh
-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://lists.csail.mit.edu/pipermail/jsr308/attachments/20081022/3a7690db/attachment.htm 


More information about the JSR308 mailing list