[type-annos-observers] ordering of annotated array brackets

Werner Dietl wdietl at gmail.com
Mon Mar 3 19:48:45 PST 2014


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-experts mailing list