Type annotations don't look very Java-like

Timo Kinnunen timo.kinnunen at gmail.com
Wed Sep 18 20:47:16 PDT 2013


Hi,

First, please correct me if I'm wrong, but it's my understanding that in
Java 8 I be able to express

1) an annotation on a parameter ONLY
2) an annotation on a parameter and its type BOTH
3) an annotation on the type of a parameter ONLY

and that each of these be distinguishable from the others, for annotation
processing purposes, for example.

Assuming the above, it strikes me that the changed grammar in addition to
not looking very Java-like is also not expressive enough for the cases 1,
2, 3 above. Suppose I'm writing my magnum opus, a class to solve the
problem of two lists in the standard library, the List:

public final class List {
  public static void bridge(List manager, java.util.List container,
java.awt.List viewer) {
    manager.bridge(container, viewer);
  }
  public void bridge(List this, java.util.List container, java.awt.List
viewer) {
    // TODO
  }
}
@Retention(value = RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.PARAMETER})
public @interface Important {
}
I want to annotate both of the bridge-methods with identical annotations
for consistency.

1) The first parameter List I want to have @Important on the parameter only.

2) For the other parameters I want one of them to have the annotation
@Important on both parameter and type and the other one have @Important on
type only.

Neither of these are possible.

The case 1 is not possible for two reasons. First because there is no
modifier that can make { TYPE_USE, PARAMETER } be treated as { PARAMETER }.
Second because a receiver can't be annotated with a parameter annotation,
unlike its static counterpart. This forces an inconsistency onto this class
design.

The case 2 is not possible because it's not possible to express the
difference. Annotating one parameter as @Important java.util.List and the
other as java.awt. at Important List is not allowed. The grammar can't express
the case where the verbose modifier-modifier was used to make { TYPE_USE,
PARAMETER } be treated as { TYPE_USE } when the type is a fully-qualified
name rather than a simple name. In other words, there is no way to write
java.util. at Important java.util.List. Thankfully, one might say. Or
mercifully.

Interestingly, it is possible and required to write @Important
java.util.List if @Important doesn't have TYPE_USE. Which means adding
TYPE_USE to an existing annotation in a library can cause compile errors
when Java 7 code switches to compiling against a Java 8 version of the
library.

I think some other mechanism is needed to put annotations on their types
because I don't think these grammar changes are very well suited for
that at all.







On Thu, Sep 19, 2013 at 1:27 AM, Alex Buckley <alex.buckley at oracle.com>wrote:

> David,
>
> It looks like there is a problem with how NetBeans handles annotations on
> type names. I confess to not knowing which NetBeans engineer is working on
> type annotations, so please inform them of the problem below.
>
> Timo,
>
>
> On 9/18/2013 12:01 PM, Timo Kinnunen wrote:
>
>> Alex, there might be bugs or unimplemented changes, but trying it out in
>> the latest NetBeans IDE 4.7 Beta, JDK 1.8.0-ea-b106 and the annotation
>> @Regarding defined like this:
>>
>> @Retention(value = RetentionPolicy.RUNTIME)
>> @Target(value = {ElementType.TYPE_USE, ElementType.PARAMETER,
>> ElementType.FIELD, ElementType.LOCAL_VARIABLE})
>> @interface Regarding { }
>>
>> Then as seen in the Trees (NetBeans development) view, right now you do
>> have to write “com.somecompany.**AnnotationTestBed.” in front of the
>> annotation to modify the modifier into becoming an annotated type instead.
>> Specifically, instead of 1xMODIFIER, 1xIDENTIFIER there will be
>> 0xMODIFIER,
>> 1xANNOTATED_TYPE.
>>
>> I don’t know where this change in semantics comes from or what its meaning
>> is, but I can see that it’s there. And as long as it is there, it can
>> become requirement for using some functionality in any tool that can
>> detect
>> its presence.
>>
>
> I'm on JDK 1.8.0-ea-b106. Here's a simplified test case:
>
> --
> import java.lang.annotation.*;
>
> @Retention(RetentionPolicy.**RUNTIME)
> @Target({ElementType.**PARAMETER})
> @interface Regarding { }
>
> public class C {
>   void m(@Regarding Object oldOne) {}
> }
> --
>
> javac will emit C.class with a RuntimeVisibleParameterAnnotat**ions
> attribute for the 'm' method, just as it did in JDK7.
>
> Then, if you add ElementType.TYPE_USE to the @Target value:
>
> @Target({ElementType.TYPE_USE, ElementType.PARAMETER})
>
> and recompile, javac will emit C.class with a second attribute,
> RuntimeVisibleTypeAnnotations, for the 'm' method. There are no surprises
> here, and no need for qualified type names.
>
> If you really want to write "java.lang. at Regarding Object oldOne", you
> can, and it's compiled correctly to just RuntimeVisibleTypeAnnotations - no
> RuntimeVisibleParameterAnnotat**ions in sight. But you don't have to.
>
> Alex
>



-- 
Have a nice day,
Timo Kinnunen


More information about the type-annotations-spec-comments mailing list