[type-annos-observers] ordering of annotated array brackets
Markus Keller
markus_keller at ch.ibm.com
Tue Mar 4 14:17:21 UTC 2014
Hi Werner, Alex
> Markus, you say that this behavior "totally makes sense". Can you
elaborate why?
AFAIK, the primary goal of the C-style "brackets after identifier"
notation is not the "mixed notation" as in Werner's examples (actually
discouraged in 10.2), but to allow a declaration of a series of variables,
where some of the variables have additional array dimensions:
private @A int @B [] fieldBase, fieldExtra @C [];
Here, fieldBase obviously has type @A int @B []. fieldExtra has the type
of fieldBase, plus the extra dimension @C []. I think it makes sense to
arrange it so that an element of array fieldExtra has the same type as
fieldBase. To achieve that, the @C [] must be the logically "outermost"
type. And by the argumentation in
http://types.cs.washington.edu/jsr308/specification/java-annotation-design.html#array-syntax
and the example in JLS8 9.7.4, the array bracket ordering for an
outside-in traversal is from left to right, so the @C [] must be inserted
in front of @B [], which gives the equivalent declaration
private @A int @C [] @B [] fieldExtra;
I agree it's not pretty, but as said in java-annotation-design.html, the
notation is bound by history. And the alternative is IMO worse: If
fieldExtra had the type @A int @B [] @C [], then its component type would
be @A int @C [] -- a type that's even more disconnected from the original
variable declaration.
Thanks,
Markus
Werner Dietl <wdietl at gmail.com> wrote on 2014-03-04 04:48:45:
> Hi Markus, Alex,
>
> the current javac behavior is as Markus describes, but might be an
> artifact of pre-type-annotation code.
> At the moment in test case:
>
> tools/javac/annotations/typeAnnotations/referenceinfos/Fields.java
>
> we only test having either all or none of the array dimensions before
> the field name (tests fieldAsArray and fieldAsArrayOld).
> I expanded the test and see the behavior that Markus describes.
> The behavior for variable declarations and method return types (with
> array dimensions after the parameter list) is consistent.
>
> Markus, you say that this behavior "totally makes sense". Can you
elaborate why?
> I agree with Alex that having the post-identifier array dimensions
> become the outermost dimensions seems counter-intuitive and makes the
> code harder to read.
> Wouldn't it be easier to read if all of these fields had the same type:
>
> @TD String @TA [] @TB [] @TC [] test;
> @TD String @TA [] @TB [] test @TC [];
> @TD String @TA [] test @TB [] @TC [];
> @TD String test @TA [] @TB [] @TC [];
>
> cu, WMD.
>
> On Mon, Mar 3, 2014 at 2:51 PM, Alex Buckley <alex.buckley at oracle.com>
wrote:
> > Hi Markus,
> >
> > Thanks for your mail and excellent test case.
> >
> > However, I don't see why the post-identifier "@C []" should be the
outermost
> > dimension, as if "int @C [] @B []" had been written. Certainly there
was no
> > hint of this in the January 2013 thread "Annotations on extended
dimension
> > in method declarations".
> >
> > I think the "followed by ..." wording of 10.2 indicates that "@C []"
should
> > be the innermost (deepest) dimension, as if "int @B [] @C []" had been
> > written.
> >
> > I am not clear if javac or java.lang.reflect is assembling the full
array
> > type in (what I consider to be) the wrong order. Werner, if you're
reading
> > this, can you help us out?
> >
> > Alex
> >
> >
> > On 3/3/2014 8:29 AM, Markus Keller wrote:
> >>
> >> JLS8 10.2 says:
> >> "In a variable declaration (§8.3, §8.4.1, §9.3, §14.14, §14.20)
except for
> >> a variable
> >> arity parameter, the array type of a variable is denoted by the array
type
> >> that appears
> >> at the beginning of the declaration, followed by any bracket pairs
that
> >> follow the
> >> variable's Identifier in the declarator."
> >>
> >> This was fine for Java < 8, where array dimension brackets were
> >> indistinguishable. But with type annotations, the order of annotated
> >> dimension brackets matters.
> >>
> >> Example: private @A int @B [] field @C [];
> >>
> >> In "1.8.0-b129", reflection says the type of "field" is "@A int @C []
@B
> >> []", and that totally makes sense. See also [1].
> >>
> >> The paragraph should e.g. say:
> >> "[..] the array type of a variable is denoted by the element type at
the
> >> beginning of the declaration, followed by any (potentially annotated)
> >> bracket pairs that follow the variable's Identifier in the
declarator,
> >> followed by any (potentially annotated) bracket pairs of the array
type at
> >> the beginning of the declaration."
> >>
> >> The ordering of consecutive array dimension brackets is currently
also
> >> undefined by the spec. There's just an informal example in 9.7.4
(which is
> >> good; it's just not a spec).
> >>
> >> Regards,
> >> Markus
> >>
> >>
> >> [1] Executable snippet to test reflection:
> >>
> >> import java.lang.annotation.*;
> >> import java.lang.reflect.*;
> >> import java.util.stream.*;
> >>
> >> @Target(ElementType.TYPE_USE) @Retention(RetentionPolicy.RUNTIME)
> >> @interface A {}
> >> @Target(ElementType.TYPE_USE) @Retention(RetentionPolicy.RUNTIME)
> >> @interface B {}
> >> @Target(ElementType.TYPE_USE) @Retention(RetentionPolicy.RUNTIME)
> >> @interface C {}
> >>
> >> public class Snippet {
> >> private @A int @B [] field @C [];
> >> private @A int @C [] @B [] fieldNormal;
> >> private @A int @B [] fieldBase, fieldExtra @C [];
> >>
> >> public static void main(String[] args) throws Exception {
> >> printField("field");
> >> printField("fieldNormal");
> >> printField("fieldBase");
> >> printField("fieldExtra");
> >> }
> >>
> >> private static void printField(String name) throws
> >> NoSuchFieldException {
> >> System.out.printf("%-12s %s\n", name + ":",
> >> toString(Snippet.class.getDeclaredField(name).getAnnotatedType()));
> >> }
> >>
> >> private static String toString(AnnotatedType annotatedType) {
> >> StringBuilder sb = new StringBuilder();
> >> while (annotatedType instanceof AnnotatedArrayType) {
> >> sb.append("
> >> ").append(toString(annotatedType.getAnnotations())).append("[]");
> >> annotatedType = ((AnnotatedArrayType)
> >> annotatedType).getAnnotatedGenericComponentType();
> >> }
> >> Type type = annotatedType.getType();
> >> sb.insert(0, type.toString());
> >> sb.insert(0, toString(annotatedType.getAnnotations()));
> >> return sb.toString();
> >> }
> >>
> >> private static String toString(Annotation[] annotations) {
> >> return Stream.of(annotations).map(Snippet::toSimpleString).
> >> collect(Collectors.joining(" ", "", " "));
> >> }
> >>
> >> public static String toSimpleString(Annotation a) {
> >> return "@" + a.annotationType().getSimpleName();
> >> }
> >> }
> >>
> >
>
>
>
> --
> http://www.google.com/profiles/wdietl
>
More information about the type-annotations-spec-observers
mailing list