Hello Oliver, This is long-standing if surprising and under-documented behavior.
The getGenericFoo methods, when generic type information is present, give a source-level view of the element. At a source level, the implicit outer this parameter is not present and thus omitted by constructor.getGenericParameterTypes for the constructor in question.
HTH, -Joe On 2/26/2021 5:41 AM, Oliver Drotbohm wrote:
Previously sent to the wrong list. Sorry for the double post. Von: Oliver Drotbohm <odrotb...@vmware.com> Betreff: Inconsistency in Constructor.getGenericParameterTypes() Datum: 25. Februar 2021 um 10:03:12 MEZ An: jdk-...@openjdk.java.net Hi all, we've just ran into the following issue: for a non-static, generic inner class with a constructor declaring a generic parameter, a call to constructor.getGenericParameterTypes() does not return the enclosing class parameter type. Is that by intention? If so, what's the reasoning behind that? Here's a the output of a reproducer (below): static class StaticGeneric<T> - names: value, string static class StaticGeneric<T> - parameters: [class java.lang.Object, class java.lang.String] static class StaticGeneric<T> - generic parameters: [T, class java.lang.String] class NonStaticGeneric<T> - names: this$0, value, String class NonStaticGeneric<T> - parameters: [class Sample, class java.lang.Object, class java.lang.String] class NonStaticGeneric<T> - generic parameters: [T, class java.lang.String] class NonStaticNonGeneric - names: this$0, String class NonStaticNonGeneric - parameters: [class Sample, class java.lang.String] class NonStaticNonGeneric - generic parameters: [class Sample, class java.lang.String] Note how the constructor of the NonStaticGeneric<T> type exposes three parameter names, three parameter types but omits the enclosing class parameter in the list of generic parameter types. Tested on JDK 8 to 15. Same behavior. Cheers, Ollie class Sample { public static void main(String[] args) { Constructor<?> first = StaticGeneric.class.getDeclaredConstructors()[0]; System.out.println("static class StaticGeneric<T> - names: " + Arrays.stream(first.getParameters()).map(Parameter::getName).collect(Collectors.joining(", "))); System.out.println("static class StaticGeneric<T> - parameters: " + Arrays.toString(first.getParameterTypes())); System.out.println( "static class StaticGeneric<T> - generic parameters: " + Arrays.toString(first.getGenericParameterTypes())); System.out.println(); Constructor<?> second = NonStaticGeneric.class.getDeclaredConstructors()[0]; System.out.println("class NonStaticGeneric<T> - names: " + Arrays.stream(second.getParameters()).map(Parameter::getName).collect(Collectors.joining(", "))); System.out.println("class NonStaticGeneric<T> - parameters: " + Arrays.toString(second.getParameterTypes())); System.out .println( "class NonStaticGeneric<T> - generic parameters: " + Arrays.toString(second.getGenericParameterTypes())); System.out.println(); Constructor<?> third = NonStaticNonGeneric.class.getDeclaredConstructors()[0]; System.out.println("class NonStaticNonGeneric - names: " + Arrays.stream(third.getParameters()).map(Parameter::getName).collect(Collectors.joining(", "))); System.out.println("class NonStaticNonGeneric - parameters: " + Arrays.toString(third.getParameterTypes())); System.out .println( "class NonStaticNonGeneric - generic parameters: " + Arrays.toString(third.getGenericParameterTypes())); } static class StaticGeneric<T> { StaticGeneric(T value, String string) {} } class NonStaticGeneric<T> { NonStaticGeneric(T value, String String) {} } class NonStaticNonGeneric { NonStaticNonGeneric(String String) {} } }