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 >>>> >>> >>> >