Inconsistency in Constructor.getGenericParameterTypes()
Joe Darcy
joe.darcy at oracle.com
Mon Mar 1 21:35:59 UTC 2021
Hi Oliver,
Perhaps the time has come to make a run at discussing this situation in
the javadoc. One challenge in writing this material up is to phrase and
structure the text so it offers a net-clarification of the situation. In
other words, to not distract or confuse most readers on what is usually
a tricky detail.
The @apiNote javadoc tag offers a mechanism to separate such discussion.
Thanks,
-Joe
On 2/26/2021 2:20 PM, Oliver Drotbohm wrote:
> Hi Joe,
>
> thanks for the explanation. We switched to rather iterating over ….getParameters() and take it from there. Do you think it makes sense to leave a note about this in the Javadoc?
>
> Cheers,
> Ollie
>
>> Am 26.02.2021 um 22:38 schrieb Joe Darcy <joe.darcy at oracle.com>:
>>
>> 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 <odrotbohm at vmware.com>
>>> Betreff: Inconsistency in Constructor.getGenericParameterTypes()
>>> Datum: 25. Februar 2021 um 10:03:12 MEZ
>>> An: jdk-dev at 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) {}
>>> }
>>> }
>>>
More information about the core-libs-dev
mailing list