Type annotations don't look very Java-like
Timo Kinnunen
timo.kinnunen at gmail.com
Mon Sep 23 14:03:26 PDT 2013
Hi,
On Thu, Sep 19, 2013 at 6:47 PM, Michael Ernst <mernst at cs.washington.edu>wrote:
> Timo-
>
> It's possible to write ugly code in any programming language, including
> Java 7 -- just like it is possible to write ugly prose or specious
> arguments in any natural language. That says nothing about the language or
> its design.
>
I didn't set out to make the code as ugly as possible, in fact the only
stylistic choice that could be argued to have been more ugly than the
alternative was the choice of putting @Nullable before @Counted rather than
the other way around. Other than that the samples are just using Type
Annotations to annotate types. In fact the method
void innerMethod(@Any Outer. at Backer Middle. at Counted Inner this, @Any
Outer. at Backer Middle. at Nullable @Counted Inner other) { ... }
is the example method from JSR308 Specification section 2.1 with a second
@Nullable parameter and written using plausible real-world names:
class Outer {
class Middle {
class Inner {
void innerMethod(@A Outer. at B Middle. at C Inner this) { ... }
}
}
}
Likewise the methods
callingJava7Way(@Regarding Example oldOne) { ... }
callingJava8Way(com.**somecompany.AnnotationTestBed.**@Regarding Example
newOne) { ... }
are written using plausible names with the parameters adapted from a field
annotation example from JSR308 Specification section 2.3:
@FAnno Object field4; // legal, one field annotation
java.lang. @FTAnno Object field12 // legal, one type annotation
That said, I agree with you that the code looks ugly. It is unfortunate
that - given how much potential Type Annotations have - the grammar makes
code using Type Annotations in some circumstances really ugly.
>
> You are incorrect in claiming that fully-qualified names are required for
> type annotations. If your argument is predicated on this incorrect
> assumption (or on a bug in some specific tool), then your arguments are
> invalid. Would it be possible to base a discussion on the specification
> (or even to double-check against the reference implementation)?
>
If you are writing your own annotations and can write them freely any way
you want then fully-qualified names are not necessary. If you are using
someone else's annotations and need to coax some specific combination out
of javac then not only do you need to use fully qualified names in one case
(field12), you need to use generics in another case (field15):
public class Object<java_lang_Object extends java.lang.Object> {
@FAnno Object field4; // legal, one field annotation
@TAnno Object field5; // legal, one type annotation
@FTAnno Object field6; // legal, one field annotation and one
type annotation
@FAnno java.lang.Object field7; // legal, one field annotation
//@TAnno java.lang.Object field8; // illegal
//@FTAnno java.lang.Object field9; // doesn't work in b106, but legal,
one field annotation
//java.lang. at FAnno Object field10; // illegal
java.lang. at TAnno Object field11; // legal, one type annotation
java.lang. at FTAnno Object field12; // legal, one type annotation
@FAnno java_lang_Object field13; // seems legal, one field annotation
@TAnno java_lang_Object field14; // seems legal, one type annotation
@FTAnno java_lang_Object field15; // seems legal, one field annotation
and one type annotation
}
Yet I don't know why @FAnno and @TAnno mean different things here. Or why
@FTAnno has to exists at all. The specification doesn't have any good ideas
either: "We have not found an example where such a meta-annotation is
desirable for a newly-created annotation; although it is legal".
The best counter-example I can come up with is
@Deprecated public final Integer field;
in which @Deprecated means that code relying on the field existing may have
to change in the future.
But you could also read that to mean that code relying on the field
containing an expected kind of value may have to change in the future.
Likewise for methods. Code relying on a method existing, beware! Or code
relying on the result of calling a method, beware! Whether something is a
declaration or a type annotation can be a matter of a viewpoint.
So rewrite history so field declaration annotations have always meant type
use annotations of fields, method declaration annotations have always meant
type use annotations of non-void return values, skip annotations on array
dimensions (you should use collections or proper low-level structures
instead), introduce annotatable real type aliases using <Object O> syntax,
stay backwards compatible for free and stop butchering my type names,
please.
>
If you have concerns about a NetBeans bug or about the syntax of lambda,
> please direct those elsewhere; they don't belong on this list.
>
> Thanks!
>
> -Mike
>
>
>
> Subject: Type annotations don't look very Java-like
>> From: Timo Kinnunen <timo.kinnunen at gmail.com>
>> To: type-annotations-spec-**comments at openjdk.java.net<type-annotations-spec-comments at openjdk.java.net>
>> Date: Wed, 18 Sep 2013 22:01:13 +0300
>>
>>
>> This is a repost of a comment from Mark Reinhold’s blog with additional
>> comments below.
>>
>> I have to agree, both Lambdas and Type Annotations that I've been looking
>> forward to don't look very Java-like at all. Lambdas add ugly syntax and
>> Type Annotations break the simplicity of nested scoping.
>> I'd love to see a list of what other options the EG considered and why
>> they
>> were rejected for what we have currently when Public Review phase starts.
>>
>> Here's Lambda with -> syntax:
>>
>> list.stream().map((Runnable runnable) -> { new Thread(runnable) }
>> ).forEach(thread -> thread.start());
>>
>> Why "->" when "for" is just as many keys to press and no key-combinations:
>>
>> list.stream().map(for(Runnable runnable) { new Thread(runnable) }
>> ).forEach(for thread thread.start());
>>
>> And Type Annotations, just look at this method signature:
>>
>> void innerMethod(@Any Outer. at Backer Middle. at Counted Inner this, @Any
>> Outer. at Backer Middle. at Nullable @Counted Inner other) { ... }
>>
>> How do you suppose a word-wrapping text-editor would think they are
>> grouped? Care to guess if it matches how they group semantically? Yep, the
>> empty " " character is now more significant than the "." character, which
>> is unbelievable.
>>
>> And if that wasn't enough, Type Annotations also lets you express the
>> difference between annotations applied to a parameter and annotations
>> applied to the type of the parameter. Here's how an annotation is applied
>> to the parameter:
>>
>> void callingJava7Way(@Regarding Example oldOne) { ... }
>>
>> And to make the annotation apply to the type of the parameter, you do
>> this:
>>
>> callingJava8Way(com.**somecompany.AnnotationTestBed.**@Regarding Example
>> newOne) { ... }
>>
>> That has got to be the most verbose modifier of another modifier I've ever
>> seen in any programming language ever and whoever came up with it deserves
>> some sort of a prize.
>>
>> Alex Buckley replied:
>> “You don't have to use qualified names with type annotations. To write an
>> annotation on the type of a formal parameter, as opposed to the
>> declaration
>> of the formal parameter, you just add @Target(ElementType.TYPE_USE) to the
>> annotation's own type declaration. Then, "@Regarding Example oldOne" means
>> @Regarding applies to this particular use of the Example type, rather than
>> to the oldOne declaration.
>>
>> More comments on type annotations? Send them to the
>> type-annotations-spec-comments at OpenJDK.”
>>
>> 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.
>>
>>
>>
>> --
>> Have a nice day,
>> Timo Kinnunen
>>
>
--
Have a nice day,
Timo Kinnunen
+358445405900, +37258352396
More information about the type-annotations-spec-comments
mailing list