Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Annotation attributes with type parameters

When you define a Java interface, it's possible to declare a method with type parameters, for example like this:

public interface ExampleInterface {     <E extends Enum<E>> Class<E> options(); } 

The same thing does not work in an annotation. This, for example, is illegal:

public @interface ExampleAnnotation {     <E extends Enum<E>> Class<E> options(); } 

I can get what I'm after by using the raw type Enum:

public @interface ExampleAnnotation {     @SuppressWarnings("rawtypes")     Class<? extends Enum> options(); } 

What exactly is the reason why it is not possible to declare annotation attributes with type parameters?

like image 350
Jesper Avatar asked Sep 29 '11 08:09

Jesper


People also ask

What is the use of @interface annotation?

The @interface element is used to declare an annotation.

What is @interface annotation in Java?

Annotation is defined like a ordinary Java interface, but with an '@' preceding the interface keyword (i.e., @interface ). You can declare methods inside an annotation definition (just like declaring abstract method inside an interface). These methods are called elements instead.

What is the annotation used to define attributes for an element?

We can also explicitly specify the attributes in a @Test annotation. Test attributes are the test specific, and they are specified at the right next to the @Test annotation.

What is type annotation in Java?

Type Annotations are annotations that can be placed anywhere you use a type. This includes the new operator, type casts, implements clauses and throws clauses. Type Annotations allow improved analysis of Java code and can ensure even stronger type checking.


1 Answers

I think it is possible, but it requires lots of additions to language spec, which is not justified.

First, for you enum example, you could use Class<? extends Enum<?>> options.

There is another problem in Class<? extends Enum> options: since Enum.class is a Class<Enum> which is a Class<? extends Enum>, it's legal to options=Enum.class

That can't happen with Class<? extends Enum<?>> options, because Enum is not a subtype of Enum<?>, a rather accidental fact in the messy raw type treatments.

Back to the general problem. Since among limited attribute types, Class is the only one with a type parameter, and wildcard usually is expressive enough, your concern isn't very much worth addressing.

Let's generalize the problem even further, suppose there are more attribute types, and wildcard isn't powerful enough in many cases. For example, let's say Map is allowed, e.g.

Map<String,Integer> options();  options={"a":1, "b":2} // suppose we have "map literal" 

Suppose we want an attrbite type to be Map<x,x> for any type x. That can't be expressed with wildcards - Map<?,?> means rather Map<x,y> for any x,y.

One approach is to allow type parameters for a type: <X>Map<X,X>. This is actually quite useful in general. But it's a major change to type system.

Another approach is to reinterpret type parameters for methods in an annotation type.

<X> Map<X,X> options();  options={ "a":"a", "b":"b" }  // infer X=String 

this doesn't work at all in the current understanding of method type parameters, inference rules, inheritance rules etc. We need to change/add a lot of things to make it work.

In either approaches, it's a problem how to deliver X to annotation processors. We'll have to invent some additional mechanism to carry type arguments with instances.

like image 112
irreputable Avatar answered Oct 04 '22 07:10

irreputable