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 <marti...@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.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 >>>>>> >>>>> >>>>> >>> >