Problem with method references

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Fri Jan 14 01:24:38 PST 2011


On 14/01/11 07:53, Peter Levart wrote:
> On 01/04/11, Maurizio Cimadamore wrote:
>> On 03/01/11 10:10, Tomasz Kowalczewski wrote:
>>> package org.tkowalcz.lambda.extractor;
>>>
>>> public class LambdaInConstructorExample {
>>>
>>>     public static void main( final String[] args ) {
>>>       // Compiles fine
>>>       Extractor x = LambdaInConstructorExample#getArgCount;
>>>     }
>>>
>>>     public LambdaInConstructorExample() {
>>>       // Error
>>>       Extractor x = LambdaInConstructorExample#getArgCount;
>>>     }
>>>
>>>     public int getArgCount() {
>>>       return 1;
>>>     }
>>> }
>> There is no bug here. The first method reference compiles because a
>> non-static method is being referenced from a static context - in such
>> cases, the following expansion is automagically applied by the compiler:
>>
>> If f is an instance method of Z whose signature is A,B->C, then #obj.f
>> is of type A,B->C and #Z.f is of type Z,A,B->C.
>>
>> Which means that, in the first case, the compiler is looking for a
>> signature of the kind (LambdaInConstructorExample)->int.
>>
>> Since the second method reference occurs in a non-static context, no
>> automatic expansion is applied, which means the compiler will look for a
>> signature of the kind ()->int.
>>
>> Now, depending on how you declare the target method in the SAM type
>> Extractor, you will not be able to get both method references to
>> compile, as the compiler will be looking for different signatures. I
>> guess that, looking at your output, your SAM type declaration looks like
>> the following:
>>
>> interface Extractor {
>> int getX(LambdaInConstructorExample arg);
>> }
>>
>> Maurizio
>>
> Hello Maurizio,
>
> I see that referencing instance methods from static context is a desirable feature, but syntax-wise I aggree with Neal that the same expression should not change its meaning if moved from static to instance context or vice-versa (when both contexts are legal). So I propose that the syntax:
>
>    #methodName
>
> be made illegal for referencing instance methods from static context.
I agree - since #methodName is essentially a shortcut for 
this#methodName, it is sensible to reject it in a static context.
Thanks for the example - I will make sure to add it to our regression 
tests as soon as I add support for #this.

Maurizio
> for example (using infix '#' - equivalent is possible with prefix '#'):
>
> class C {
>
>    public int m(String s) { ... }
>
>    public static int sm(String s) { ... }
>
>    C() {
>          StringToInt f1 = this#m;
>          StringToInt f2 = #m; // equivalent as above
>          CStringToInt f3 = C#m;
>
>         StringToInt f4 = C#sm;
>         StringToInt f5 = #sm; // equivalent as above
>         StringToInt f6 = this#sm; // equivalent as above (to be consistent with method invocation)
>
>          new Runnable() {
>            public void run() {
>              StringToInt f1 = C.this#m;
>              CStringToInt f2 = C#m;
>            }
>          }.run();
>    }
>
>    static {
>      C c = new C();
>
>      StringToInt f1 = c#m;
>      // #m - illegal
>      CStringToInt f2 = C#m;
>
>      StringToInt f3 = C#sm;
>      StringToInt f4 = #sm; // equivalent as above
>      StringToInt f5 = c#sm; // equivalent as above (to be consistent with method invocation)
>    }
>
>    interface StringToInt {
>      int apply(String s);
>    }
>
>    interface CStringToInt {
>      int apply(C c, String s);
>    }
> }
>
>
> Regards, Peter



More information about the lambda-dev mailing list