Inconsistency in Constructor.getGenericParameterTypes()
Remi Forax
forax at univ-mlv.fr
Mon Mar 1 22:16:56 UTC 2021
Hi Joe,
i think the overview of the package java.lang.reflect should discuss the fact that the reflection view is what is stored in the classfile, not exactly a reflection of the java code.
So depending on what you are requesting, you can see synthetic parameters generated by javac or only the Java view because the Java view is directly stored in an attributes like with generics
Rémi
----- Mail original -----
> De: "joe darcy" <joe.darcy at oracle.com>
> À: "Oliver Drotbohm" <odrotbohm at vmware.com>
> Cc: "core-libs-dev" <core-libs-dev at openjdk.java.net>
> Envoyé: Lundi 1 Mars 2021 22:35:59
> Objet: Re: Inconsistency in Constructor.getGenericParameterTypes()
> 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