Number of formal parameters of anonymous class constructor

Alex Buckley alex.buckley at oracle.com
Tue Aug 4 18:12:55 UTC 2015


Here's one possible answer:

---
Yes, the second parameter being the synthetic Outer contradicts the JLS.

No, I don't expect javac to change.

No, I don't expect the JLS to change. First, the contradiction doesn't 
matter -- an anonymous class can only be instantiated at the point where 
it's declared, so the only compiler which needs to pass arguments to the 
ctor is the compiler which generated the ctor. Second, any alternative 
text which allows javac's current behavior will be looser than the 
current text, so it will be even less testable by JCK.

This is the danger of hiding a compiler spec inside a language spec, but 
we're stuck with it.
---

Here's another possible answer:

---
No, the second parameter being the synthetic Outer does not contradict 
the JLS, because the only compiler which needs to pass arguments to the 
ctor is the compiler which generated the ctor, and thus synthetic 
parameters are implementation details "below" the level of things 
specified by the JLS.

Yes, it would be cleaner if javac changed to follow 15.9.5.1 exactly.
---

Alex

On 8/4/2015 7:06 AM, konstantin barzilovich wrote:
> Hello Alex,
>
> Thank you for quick response.
> I agree that JLS 15.9.5.1 does not prohibit the existence of additional
> parameter, but lets consider A ctor with one explicit formal parameter
>
> public A (Integer i) {}
>
> and anonymous class instance creation expression is:
>
> A a = newOuter().newA(5) {};
>
> In this case, following jls-15.9.5.1-100-B.1:
>
> "...The n'th formal parameter e corresponds to the n-1'th actual argument"
>
> we expect anonymous ctor with second parameter of type Integer. But the
> second parameter will be synthetic Outer.
> Doesn't it contradict the assertion?
> If it is implementation-free, then we don't know what type of second
> parameter should be.
>
> Thanks,
> Konstantin.
>
> On 03.08.2015 21:33, Alex Buckley wrote:
>> On 8/3/2015 5:47 AM, konstantin barzilovich wrote:
>>> In chapter 15.9.5.1 in JLS signature of anonymous constructor is
>>> described.
>>> In case S is inner non-static class (see the minimal example)
>>>
>>> classOuter {
>>>      publicOuter() {}
>>>      classA  {
>>>          publicA() {}
>>>      }
>>>      public voidfoo(){
>>>          A a =newOuter().newA(){};
>>>      }
>>> }
>>>
>>> we expect to have one formal parameter of type Outer according to
>>> jls-15.9.5.1-100-B and jls-15.9.5.1-100-B.1.
>>
>> Let's look at what we have. 'S' is the class A, and with i as the
>> newly created instance of the anonymous class:
>>
>> a) The immediately enclosing instance of i is the instance of Outer on
>> which foo() was called.
>> b) The immediately enclosing instance of i-with-respect-to-A is the
>> instance of Outer produced by "new Outer()".
>>
>> In 15.9.5.1, the JLS prescribes the form of the anonymous class ctor
>> (note the phrase "implicitly declared"). In particular, the JLS
>> prescribes that (b) is encoded as the first formal parameter of the
>> ctor. I guess you could call it the "receiver parameter" but I won't.
>>
>> You can see the encoding of (b) via reflection. Compile Outer.java
>> with javac -parameters, then reflect over the anonymous class to get
>> its java.lang.reflect.Constructor, then call getParameters(). Element
>> 0 should return true for isImplicit().
>>
>>> But I try to get parameters of constructor via reflection and it has two
>>> parameters both of type Outer.
>>> I guess, the second one is a receiver parameter, but it isn't mentioned
>>> in jls-15.9.5.1-100-B.1.
>>> Could you please clarify this situation?
>>
>> The JLS does not prescribe the encoding of (a) into the ctor. It is
>> likely that javac is storing (a) as the second parameter, but that's
>> an implementation detail which javac is free to change. I guess you
>> could call it the "environment parameter" but I won't. Point is, JLS
>> 15.9.5.1 does not prohibit the existence of the second parameter.
>>
>> If you reflect with getParameters(), element 1 should return false for
>> isImplicit() and true for isSynthetic().
>>
>> Alex
>


More information about the compiler-dev mailing list