On 22/07/2016 4:50 AM, Joel Borggrén-Franck 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.

It is an irregularity - for want of a better word. See:

https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3

"An instance of an inner class I whose declaration occurs in a static context has no lexically enclosing instances. "

David
-----

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




Reply via email to