[type-annos-observers] Type annotations don't look very Java-like
Alex Buckley
alex.buckley at oracle.com
Thu Sep 19 10:52:12 PDT 2013
Yes, this is working as designed. Your first @Important is a type
annotation, so goes into RuntimeVisibleTypeAnnotations; your second
@Important is both a type annotation and a declaration annotation, so
goes into RuntimeVisibleTypeAnnotations and
RuntimeVisibleParameterAnnotations.
Alex
On 9/19/2013 9:28 AM, Timo Kinnunen wrote:
> Hi,
>
> A small correction to case 2 presented in this:
>
> "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."
>
> It seems I was wrong about case 2 and it is possible after all. Here's what
> the method looks like:
>
> public final class List {
> public <java_awt_List extends java.awt.List> void genericBridge(
> List this,
> java.util. at Important List container,
> @Important java_awt_List viewer) {
> // TODO
> }
> }
> This produces the following javap -v -p -s output that satisfies the
> requirement for case 2:
>
> RuntimeVisibleTypeAnnotations:
> 0: #24(): METHOD_FORMAL_PARAMETER, param_index=1
> 1: #24(): METHOD_FORMAL_PARAMETER, param_index=0
> RuntimeVisibleParameterAnnotations:
> parameter 0:
> parameter 1:
> 0: #24()
>
>
> Is this working as designed or a bit of generics type programming?
>
>
>
>
> On Thu, Sep 19, 2013 at 6:47 AM, Timo Kinnunen <timo.kinnunen at gmail.com>wrote:
>
>> 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-observers
mailing list