Anonymous class with parameterized super type, constructor formal parameters

Georgiy Rakov georgiy.rakov at oracle.com
Thu Jun 11 15:53:29 UTC 2015


Hello,

assertion jls-15.9.5.1-100-A.1 specifies:

    The actual arguments to the class instance creation expression are
    used to determine a constructor |cs| of S, using the same rules as
    for method invocations (§15.12
    <https://baloo.ru.oracle.com/jenkins/job/jck9-lang/lastSuccessfulBuild/artifact/build/out/htmlout/jls-15.html#jls-15.12>).
    /_*The type of each formal parameter of the anonymous constructor
    must be identical to the corresponding formal parameter of
    *_//_*|cs|*_/.

I'd like to point to the emphasized part of the assertion above which 
states that the formal parameters of the anonymous class constructor are 
identical to those of the corresponding super class constructor.

However let's consider following example:

    import java.lang.reflect.Constructor;
    import java.util.Arrays;
    import java.util.stream.Stream;

    class Test7A<T> {
         Test7A(T t) {}
    }
    public class Test7 {
         public static void main(String[] args) throws
    NoSuchMethodException {
             Test7A<String> a = new Test7A<>("a"){};
             System.out.println("Diamond case:");
             printlnParameters("anonymous class constructor",
    a.getClass().getDeclaredConstructor(String.class));
             printlnParameters("super class constructor",
    a.getClass().getSuperclass().getDeclaredConstructor(Object.class));

             System.out.println();
             a = new Test7A<String>("a"){};
             System.out.println("Explicit type arguments case:");
             printlnParameters("anonymous class constructor",
    a.getClass().getDeclaredConstructor(String.class));
             printlnParameters("super class constructor",
    a.getClass().getSuperclass().getDeclaredConstructor(Object.class));
         }
         static void printlnParameters(String label, Constructor c) {
             Stream<String> stream =
    Arrays.stream(c.getParameters()).map(p -> p.getType().toString());
             System.out.println("  " + label + ": " +
    Arrays.toString(stream.toArray()));
         }
    }

The output of this program is:

    Diamond case:
       anonymous class constructor: [class java.lang.String]
       super class constructor: [class java.lang.Object]

    Explicit type arguments case:
       anonymous class constructor: [class java.lang.String]
       super class constructor: [class java.lang.Object]

As you can see the formal parameters for the anonymous class constructor 
and those of the corresponding base class constructor are different. 
Could you please tell if you consider this as a discrepancy between 
javac and specification which should be fixed.

BTW: this alludes to my previous letter, that is, provided the anonymous 
classes in these cases were generic and its instances were just 
parameterization of those the formal parameters naturally would be 
identical, I believe.

Thank you,
Georgiy.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20150611/72ce7916/attachment-0001.html>
-------------- next part --------------
import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.stream.Stream;

class Test7A<T> {
    Test7A(T t) {}
}
public class Test7 {
    public static void main(String[] args) throws NoSuchMethodException {
        Test7A<String> a = new Test7A<>("a"){};
        System.out.println("Diamond case:");
        printlnParameters("anonymous class constructor", a.getClass().getDeclaredConstructor(String.class));
        printlnParameters("super class constructor",
                a.getClass().getSuperclass().getDeclaredConstructor(Object.class));

        System.out.println();
        a = new Test7A<String>("a"){};
        System.out.println("Explicit type arguments case:");
        printlnParameters("anonymous class constructor", a.getClass().getDeclaredConstructor(String.class));
        printlnParameters("super class constructor",
                a.getClass().getSuperclass().getDeclaredConstructor(Object.class));
    }
    static void printlnParameters(String label, Constructor c) {
        Stream<String> stream = Arrays.stream(c.getParameters()).map(p -> p.getType().toString());
        System.out.println("  " + label + ": " + Arrays.toString(stream.toArray()));
    }
}


More information about the compiler-dev mailing list