RFR: JDK-8044629: (reflect) Constructor.getAnnotatedReceiverType() returns wrong value

Martin Buchholz martinrb at google.com
Tue Jul 26 00:46:04 UTC 2016


I filed a couple of bugs.  Here's a relevant JIRA search:

https://bugs.openjdk.java.net/issues/?jql=Subcomponent%20%3D%20java.lang%3Areflect%20AND%20watcher%20%3D%20martin

Because of the trickiness of local vs inner classes, Alex may want to make
a decision on the correct behavior.


On Fri, Jul 22, 2016 at 6:11 PM, Martin Buchholz <martinrb at google.com>
wrote:

> Bug 8029042: Receiver parameter not supported on local class constructor
> also suggests that a local class of an instance method "is a perfectly
> good inner class" and so getAnnotatedReceiverType should treat them
> equivalently.
>
> On Thu, Jul 21, 2016 at 11:50 AM, Joel Borggrén-Franck <
> joel.borggren.franck at gmail.com> wrote:
>
>> This is the first time I noticed the second paragraph of $14.3, strange
>> indeed! I'd ping compiler-dev with this, Alex will probably know if this is
>> a spec bug in $14.3 or just an irregularity.
>>
>> Cheers
>> /Joel
>>
>> On Jul 21, 2016 20:39, "Martin Buchholz" <martinrb at google.com> wrote:
>>
>>> Joel, Thanks for responding so quickly!
>>>
>>> Here' s a slightly modified version of my repro recipe:
>>> You can see that local classes in instance methods have a receiver type,
>>> just like a member inner class.
>>> local classes in static methods (naturally!) do not.  I expect the two
>>> flavors of local classes to be treated differently.
>>>
>>> I've never understood why
>>> """All local classes are inner classes"""
>>> (even in a static method?)
>>> https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.3
>>>
>>>
>>> import java.lang.reflect.Constructor;
>>>
>>> public class LocalClassReceiverTypeBug {
>>>     public static void main(String[] args) throws Throwable {
>>>         class StaticLocal {}
>>>         printConstructor(StaticLocal.class);
>>>         new LocalClassReceiverTypeBug().instanceMain();
>>>     }
>>>
>>>     public void instanceMain() throws Throwable {
>>>         class InstanceLocal {}
>>>         printConstructor(InstanceLocal.class);
>>>         printConstructor(Inner.class);
>>>         // printConstructor(Nested.class);
>>>     }
>>>
>>>     static class Nested {}
>>>     class Inner {}
>>>
>>>     static void printConstructor(Class<?> klazz) {
>>>         Constructor<?>[] constructors = klazz.getDeclaredConstructors();
>>>         if (constructors.length != 1) throw new AssertionError();
>>>         Constructor<?> constructor = constructors[0];
>>>         System.out.printf("constructor=%s receivertype=%s%n",
>>>                           constructor,
>>>                           constructor.getAnnotatedReceiverType());
>>>     }
>>> }
>>> ==> javac -source 9 -Xlint:all LocalClassReceiverTypeBug.java
>>> ==> java -esa -ea LocalClassReceiverTypeBug
>>> constructor=LocalClassReceiverTypeBug$1StaticLocal() receivertype=null
>>> constructor=LocalClassReceiverTypeBug$1InstanceLocal(LocalClassReceiverTypeBug)
>>> receivertype=null
>>> constructor=LocalClassReceiverTypeBug$Inner(LocalClassReceiverTypeBug)
>>> receivertype=sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl at 1810399e
>>>
>>>
>>> On Thu, Jul 21, 2016 at 11:16 AM, Joel Borggrén-Franck <
>>> joel.borggren.franck at gmail.com> wrote:
>>>
>>>> Hi Martin,
>>>>
>>>> I'm away from my workstation at the moment, so this is from memory.
>>>> IIRC a local class is pure scoping and lacks an "outer this" which is what
>>>> you annotate for constructors. There should not be receiver type to
>>>> annotate. Since I can't run your code I can't see what's wrong but I might
>>>> be able to help if you paste the output from a run.
>>>>
>>>> Cheers
>>>> /Joel
>>>>
>>>> On Jul 21, 2016 19:49, "Martin Buchholz" <martinrb at google.com> wrote:
>>>>
>>>>> Hi Joel, Paul,
>>>>>
>>>>> A coworker ran into the change of behavior here in jdk9.
>>>>> Specifically, we noticed that a local class constructor has a receiver
>>>>> parameter, but getAnnotatedReceiverType returns null.  The changed jdk9
>>>>> spec is actually very clear about that:
>>>>>
>>>>>
>>>>> http://download.java.net/java/jdk9/docs/api/java/lang/reflect/Constructor.html#getAnnotatedReceiverType--
>>>>> """If this Executable object represents a static method or represents
>>>>> a constructor of a top level, static member, local, or anonymous class,
>>>>> then the return value is null."""
>>>>>
>>>>> BUT we can't think of any reason WHY a local inner class would be
>>>>> treated differently from an inner member class.  Why not the simple and
>>>>> obvious rule: if there is a receiver parameter, return an appropriate
>>>>> non-null AnnotatedType?
>>>>>
>>>>> You already have an excellent jtreg test, but here's what I was
>>>>> playing with:
>>>>>
>>>>> import java.lang.reflect.Constructor;
>>>>>
>>>>> public class LocalClassReceiverTypeBug {
>>>>>     public static void main(String[] args) throws Throwable {
>>>>>         class StaticLocal {}
>>>>>         printConstructor(StaticLocal.class);
>>>>>         new LocalClassReceiverTypeBug().instanceMain();
>>>>>     }
>>>>>
>>>>>     public void instanceMain() throws Throwable {
>>>>>         class InstanceLocal {}
>>>>>         printConstructor(InstanceLocal.class);
>>>>>         printConstructor(Inner.class);
>>>>>         printConstructor(Nested.class);
>>>>>     }
>>>>>
>>>>>     static class Nested {}
>>>>>     class Inner {}
>>>>>
>>>>>     static void printConstructor(Class<?> klazz) {
>>>>>         Constructor<?>[] constructors =
>>>>> klazz.getDeclaredConstructors();
>>>>>         if (constructors.length != 1) throw new AssertionError();
>>>>>         System.out.printf("constructor=%s%n", constructors[0]);
>>>>>         System.out.printf("receiver type=%s%n",
>>>>>                           constructors[0].getAnnotatedReceiverType());
>>>>>     }
>>>>> }
>>>>>
>>>>>
>>>>>
>>>>> On Wed, Aug 13, 2014 at 1:54 AM, Joel Borggren-Franck <
>>>>> joel.franck at oracle.com> wrote:
>>>>>
>>>>>> Hi Paul,
>>>>>>
>>>>>> On 2014-06-24, Paul Sandoz wrote:
>>>>>> >
>>>>>> > On Jun 17, 2014, at 6:52 PM, Joel Borggrén-Franck <
>>>>>> joel.franck at oracle.com> wrote:
>>>>>> > >
>>>>>> > > Can I get a review for this fix and javadoc clarification for
>>>>>> https://bugs.openjdk.java.net/browse/JDK-8044629
>>>>>> > >
>>>>>> >
>>>>>> > +1
>>>>>> >
>>>>>> > I never quite realised just how convoluted it was to determine that
>>>>>> a class is an inner class.
>>>>>>
>>>>>> Neither did I until I had to implement it :)
>>>>>>
>>>>>> cheers
>>>>>> /Joel
>>>>>>
>>>>>
>>>>>
>>>
>


More information about the core-libs-dev mailing list