Syntactic sugar for method chaining / fluent interfaces Syntactic sugar for method chaining / fluent interfaces Syntactic sugar for method chaining / fluent interfaces

Eirik Lygre eirik.lygre at gmail.com
Sun Nov 20 14:34:27 PST 2011


It seems that the various Java SE 8 projects have lots of care for simple
and expressive code, for example as demonstrated by the "Language / Library
/ VM co-evolution in Java SE 8" presentation from Devoxx. Hence, I wonder
if there is any interest for reviving an older suggestion about simple
method chaining / fluent interface.

I'm not really qualified to suggest the formal syntax, but it probably
boils down to this:

    A void method call "object.function(...)" evaluates to the object itself

This will be syntactic sugar (compiler only, no jvm changes), making it
possible to chain method calls across void methods. For example:

    Socket so = new SSLSocket()
                .setSendBufferSize(1024)        // void
Socket.setSendBufferSize(int)
                .setReceiveBufferSize(1024)     // void
Socket.setSendBufferSize(int)
                .setNeedClientAuth(true);       // void
SSLSocket.setNeedClientAuth(boolean)

A couple of points on the rationale for the suggestion:

* First, it will enable method chaining on a large body of existing code.
The javabeans spec says that setters should return void, and this
suggestion would automatically allow fluent use of such beans.

* It will allow a level of fluent interfaces that are otherwise not
possible, in that it will simulate a "self" return type. If you want to
 implement a fluent interface today, you would return your own type. If
somebody then created a subclass, and wanted to maintain fluency, they
would have to override all parent methods, as shown below. Of course, this
means that fluent methods added to the superclass must also be added to all
subclasses, which isn't really an ideal situation if you want to evolve an
api.

    class Socket {
        Socket setSendBufferSize(...);   // Can be chained
    }

    class SSLSocket extends Socket {
        SSLSocket setSendBufferSize(...) {                      // Change
return type, to maintain chainability
            return (SSLSocket)super.setSendBufferSize(...);     // Cast
required.
        }
    }

This is not a new idea. It was suggested for project coin, where there are
more references:

* It was suggested for project coin by Ulf Zibis (
http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/001180.html).
* I've not found much discussion, other than a quick email from Joe Darcy (
http://mail.openjdk.java.net/pipermail/coin-dev/2009-May/001768.html),
where the idea is rejected: "While fluent interfaces are fine, I don't
think using a language change  to retrofit this pattern of API usage on
code not written that way is  the best use of the language change budget."

While it was considered (and rejected) for SE 7, it might still be proper
for SE 8. Method chaning / fluent interfaces are used in pretty much all
lambda examples, as a useful code pattern. I think it's useful, too, and
think it should be made easier accessible across the language.

I've got two hopes for this email:

* First, feedback on whether the community considers this to be useful, or
not
* Second, feedback on how to proceed, if it is in fact considered useful

Eirik Lygre
eirik.lygre at gmail.com


More information about the jdk8-dev mailing list