RFR: JDK-8044629: (reflect) Constructor.getAnnotatedReceiverType() returns wrong value
Martin Buchholz
martinrb at google.com
Thu Jul 21 18:39:57 UTC 2016
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