ordering of annotated array brackets

Markus Keller markus_keller at ch.ibm.com
Mon Mar 3 16:29:42 UTC 2014


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();
    }
}



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