[type-annos-observers] ordering of annotated array brackets
Alex Buckley
alex.buckley at oracle.com
Mon Mar 3 19:51:44 UTC 2014
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();
> }
> }
>
More information about the type-annotations-spec-observers
mailing list