[type-annos-observers] annotated type of array-typed varargs parameter

Markus Keller markus_keller at ch.ibm.com
Sun Apr 6 19:43:30 UTC 2014


Hi Alex

Thanks for the clarification.

8.4.1 also defines: "a variable arity parameter, indicated by an ellipsis 
following the type." Strictly speaking, it should be "indicated by a 
(possibly annotated) ellipsis following the type".

Using 10.2 to hold the definition of a variable's type sounds good. The 
final text should also tell that annotations belong to the bracket pair or 
ellipsis that follows them, so that it's clear that the annotations are 
reason for the explicit specification of the order of the array 
dimensions.

Markus

"type-annotations-spec-observers" 
<type-annotations-spec-observers-bounces at openjdk.java.net> wrote on 
2014-04-04 21:04:39:

> From: Alex Buckley <alex.buckley at oracle.com>
> To: type-annotations-spec-experts 
<type-annotations-spec-experts at openjdk.java.net>
> Date: 2014-04-04 21:04
> Subject: Re: [type-annos-observers] annotated type of array-typed 
varargs parameter
> Sent by: "type-annotations-spec-observers" 
<type-annotations-spec-observers-bounces at openjdk.java.net>
> 
> Hi Markus,
> 
> I think it's pretty clear that the "intuitive order" is desirable, for 
> two reasons:
> 
> 1) It should be possible to refactor pArr's type to match pVar's type by 

> replacing the final [] with '...', and not change the array type of 
> pVar. That is, the following method call (in someone else's code, so 
> can't be easily changed) should keep working after the refactoring:
> 
>    var(new Object @A [] {});
> 
> 2) I see this more as a spec issue than a true design issue. Formerly, 
> the array type was specified in recursive fashion, building on the 
> component type ("the component type is the UnannType"). That's why, for 
> a variable arity parameter, it looked like the compiler was constructing 

> an array of type Object @B [] @A []. But we've generally come to specify 

> array types in a linear fashion, which would mean the compiler is deemed 

> to construct an array of type Object @A [] @B [] (or Object @A [] if you 

> omit later dimensions, as in method call above).
> 
> With reference to JDK-8038881, I'd propose to have 8.4.1 always point to 

> 10.2 for a variable arity parameter, and for 10.2 to build up the 
> parameter's type in basically the same fashion as for other array types 
> [excluding post-identifier [], of course, since they're not legal here].
> 
> Happily, JLS 15.12.2 which considers variable arity parameters speaks 
> only of the full array type T[] which is the type of the last parameter. 

> So that is unaffected by clarifications to 8.4.1 / 10.2, as long as 
> 8.4.1 / 10.2 are deterministic about the outermost dimension.
> 
> Alex
> 
> On 4/4/2014 7:14 AM, Markus Keller wrote:
> > We've found a problem with the definition of the varargs syntax on 
array
> > types. The methods "var" and "arr" below should intuitively have the 
same
> > formal parameter type "Object @A [] @B []", but that clashes with the
> > order of annotations on array dimensions:
> >
> > interface Test {
> >          void var(Object @A [] @B ... pVar);
> >          void arr(Object @A [] @B [] pArr);
> > }
> > @Target(ElementType.TYPE_USE) @interface A { }
> > @Target(ElementType.TYPE_USE) @interface B { }
> >
> > The clarification for 8.4.1 in
> > https://bugs.openjdk.java.net/browse/JDK-8038881 says: "If the formal
> > parameter is a variable arity parameter, then the declared type is an
> > array type whose component type is UnannType."
> >
> > In "var", the UnannType is "Object @A []", so the type of the 
parameter is
> > actually "Object @B [] @A []", according to the annotation order given 
in
> > 9.7.4.
> >
> > In JDK 1.8.0-b132, reflection uses the intuitive order. The snippet 
below
> > prints:
> >
> > var:   class java.lang.Object @A [] @B []
> > arr:   class java.lang.Object @A [] @B []
> >
> > That's incorrect according to JLS8. java-annotation-design.html 
doesn't
> > address this problem (just says "The varargs syntax “...” is treated
> > analogously to array brackets").
> >
> > I don't see a good solution.
> > a) Say JLS8 is right. => We lose the simple transformation that turns 
a
> > vararg into a normal array dimension by changing ... into [].
> > b) Say the above transformation must be valid. => The annotation in 
front
> > of the ... no longer applies to the outermost array type, which is 
also
> > strange, because that's the array that is constructed by the compiler 
for
> > a variable arity method invocation.
> >
> >
> >
> > 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 {}
> >
> > public class Snippet {
> >      void var(Object @A [] @B ... pVar) { }
> >      void arr(Object @A [] @B [] pArr) { }
> >
> >      public static void main(String[] args) throws Exception {
> >          printParamType(Snippet.class.getDeclaredMethod("var",
> >                  Object[][].class));
> >          printParamType(Snippet.class.getDeclaredMethod("arr",
> >                  Object[][].class));
> >      }
> >
> >      private static void printParamType(Method method) {
> >          System.out.printf("%-5s %s\n", method.getName() + ":",
> >                  toString(method.getAnnotatedParameterTypes()[0]));
> >      }
> >
> >      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();
> >      }
> > }
> >
> > Markus
> >
> 



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