New JEP: Concise Method Bodies

Dan Smith daniel.smith at oracle.com
Mon Oct 8 18:14:00 UTC 2018


> On Oct 8, 2018, at 10:50 AM, Brian Goetz <brian.goetz at oracle.com> wrote:
> 
>     class UnmodifiableFooWrapper<T> implements Foo<T> {
>         private final Foo<T> underlying;
> 
>         public void fooMethod1(args) = underlying::fooMethod1;
>         public int fooMethod2(args) = underlying::fooMethod2;
>         public long fooMethod3(args) = underlying::fooMethod3;
> 
>         public String fooMethod4(args) { 
>             // do something extra here
>             return underlying.fooMethod4(args);
>         }
>     }
> 
> If we were to eliminate these cases, much of the benefit goes away.  
> 
> Your #2 would admit the first example (because the comparator field is final), but eliminate the second; #3, #4, and #5 would also admit the second.  

Not #3, because the field is null when instance initializers run (assuming the constructor you haven't included takes a Foo<T> as an argument). For delegation to work, the method references have to be evaluated sometime _after_ the constructor body.

To support a mutable delegation target (a common feature of, e.g., the state pattern), you'd have to do #6. But perhaps we don't want to support that use case.

> In any case, an effective simplification that includes the desired use cases and stays within the intendd intuition would be to only allow bound method refs when the receiver is a compile-time constant or a final field of the current class (or possibly `this`.)  

So, #4 or #5. And for predictable semantics, that probably means #4.

>> - It's not totally clear what we do with 'this'. Kind of seems like it should be treated as the first parameter to be passed, but there are also examples in the JEP that ignore it. And is it allowed to be referenced by the receiver expression?
>> 
>> 	void reverse() = Collections::reverse; // invoke Collections.reverse(this)?
>> 	int length(String s) = String::length; // invoke s.length()?
>> 	void altMethod() = ThisClass::method; // invoke this.method()?
> 
> In existing SAM conversion, we're willing to treat `Foo::bar` as either a static method or a bound instance method (as long as we can disambiguate.)  I think what's new here is that you're saying there's some ambiguity between whether we should infer a functional interface solely from the method arguments and return, or whether (for an instance method) we should be willing to consider the receiver as an extra parameter.  The latter would enable a category of extension-method-like use cases, where we'd have static methods which take a leading pseudo-receiver, designed for use as "injectable behavior"?  And of course doing so would expand the territory where the compiler couldn't pick an overload, since we historically did overload selection _after_ the SAM type was known.  This would requiring doing it against both interpretations, and hoping exactly one answer pops up.

Yes, the problem is that the target function type is ambiguous. it could be i) (args)->return, ii) (this,args)->return, or iii) try both.

I hadn't actually thought of "try both", but my intuition was that you probably want (ii), because (i) throws information away. In practice, it would be unusual (possible, but uncommon) to implement an instance method while ignoring 'this'. This might depend on the form of the method reference, though:

- Type-qualified method ref: if you don't pass 'this' to the method, you're throwing it away. Static utility methods could be referenced with this form. Methods of the current class/supers could be referenced, too, but 'this::foo' and 'super::foo' serve the same purpose, if we allow them.

- Expression-qualified method ref: very possibly, the expression preserves the information you need from 'this', and passing 'this' to the method would be redundant. Hard to think of examples in which a user would want 'this' to be passed as a first parameter.

This makes me think that maybe we want to treat the two forms of method reference differently...

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20181008/f8ce15f4/attachment-0001.html>


More information about the amber-spec-experts mailing list