Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8225470

Constructor.getParameterAnnotations does not include implicit enclosing param

XMLWordPrintable

      ADDITIONAL SYSTEM INFORMATION :
      $ uname -a
      Linux job 4.18.0-20-generic #21~18.04.1-Ubuntu SMP Wed May 8 08:43:37 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
      $ java -version ~
      openjdk version "1.8.0_212"
      OpenJDK Runtime Environment (build 1.8.0_212-8u212-b03-0ubuntu1.18.04.1-b03)
      OpenJDK 64-Bit Server VM (build 25.212-b03, mixed mode)


      A DESCRIPTION OF THE PROBLEM :
      Javadoc for Executable#getParameterAnnotations states that "Synthetic and mandated parameters (see explanation below), such as the outer "this" parameter to an inner class constructor will be represented in the returned array."
      This is not true for the Constructor implementation.

      And it breaks the Parameter.getDeclaredAnnotations call - it returns annotations of the next parameter and fails with index error on last parameter.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile and run the provided source code

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      annotations = []
      annotations = []
      annotations = [@Scratch$Ann()]


      parameter = Scratch arg0
      parameter.getDeclaredAnnotations() = []

      parameter = java.lang.String arg1
      parameter.getDeclaredAnnotations() = []

      parameter = java.lang.String arg2
      parameter.getDeclaredAnnotations() = [@Scratch$Ann()]

      ACTUAL -
      annotations = []
      annotations = [@Scratch$Ann()]


      parameter = Scratch arg0
      parameter.getDeclaredAnnotations() = []

      parameter = java.lang.String arg1
      parameter.getDeclaredAnnotations() = [@Scratch$Ann()]

      parameter = java.lang.String arg2
      Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
      at java.lang.reflect.Parameter.getDeclaredAnnotations(Parameter.java:305)
      at Scratch.test(scratch_1.java:31)
      at Scratch.main(scratch_1.java:8)

      ---------- BEGIN SOURCE ----------
      import java.lang.annotation.*;
      import java.lang.reflect.Constructor;
      import java.lang.reflect.Parameter;
      import java.util.Arrays;

      class Scratch {
      public static void main(String[] args) {
      new Scratch().test();
      }

      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.PARAMETER)
      @interface Ann {}

      class Test {
      Test(String first, @Ann String second) {}
      }

      public void test() {

      Constructor<?> constructor = Test.class.getDeclaredConstructors()[0];

      for (Annotation[] annotations : constructor.getParameterAnnotations()) {
      System.out.println("annotations = " + Arrays.toString(annotations));
      }

      System.out.println("\n");

      for (Parameter parameter : constructor.getParameters()) {
      System.out.println("parameter = " + parameter);
      System.out.println("parameter.getDeclaredAnnotations() = " + Arrays.toString(parameter.getDeclaredAnnotations()));
      System.out.println();
      }
      }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      When working with Parameter arrays you can check if `parameter.getDeclaringExecutable().getDeclaringClass().getEnclosingClass() != null` and get annotations 'from previous parameter' accordingly.

            fmatte Fairoz Matte
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: