RFR: JDK-8044629: (reflect) Constructor.getAnnotatedReceiverType() returns wrong value
Joel Borggrén-Franck
joel.borggren.franck at gmail.com
Thu Jul 21 18:50:59 UTC 2016
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