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.fra...@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" <marti...@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@1810399e >> >> >> On Thu, Jul 21, 2016 at 11:16 AM, Joel Borggrén-Franck < >> joel.borggren.fra...@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" <marti...@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.fra...@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.fra...@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 >>>>> >>>> >>>> >>