Project Lambda: Closures, Extensions, Mixins, Oh My!
NOTE: Documentation and code presented here is based on living and changing documentation by the JSR committee and subject to change causing this article to be inaccurate or outdated. I am also not affiliated with the JSR or its members.
This blog article is probably a bit premature being it is centered around JDK 8, but I think it is interesting enough to cover when planning new frameworks. JDK 8 is not being planned for release until late 2012. Anyways, bare with me. One of my favorite expected features is around Project Lambda (http://openjdk.java.net/projects/lambda/). Project lambda is all about adding “closures” or “lambda expressions” to the Java language. Many people know about closures from several other languages (C#, Ruby, Groovy, etc), but not many know about how Java plans to implement them. The mechanism Java has selected to use has some interesting caveats and useful features.
Before I get to what I think is cool, let me give a little background and perspective. Project lambda contains two main features: closures and defender methods. Closures are essentially what you have seen with other languages but are strongly typed. Defender methods are a feature used to handle the backwards compatibility of JDK with closures in mind. More on that in a bit. A simple example of a closure would be:
List<String> list = …; Collections.sort(list, #{ String a1, String a2 -> a1.compareTo(a2); } ); |
Compare that to the implementation today:
List<String> list… Collections.sort(list, new Comparator<String>() { public int compare(String a1, String a2) { return a1.compareTo(a2); } }); |
The idea is that you remove all the boilerplate code around the definition and purely specify the arguments, their types (as Java is strongly type), and the body, which is normally one line of code. The types are actually optional (per the current spec at least) if they can be inferred from the underlying code assignment. For example, in the above example, the compiler knows that the Comparator must be a definition of Comparator, which means the method must be compareTo(String, String). Thus, the two parameters must be String. But enough of that. There is plenty more information on closures in the spec such as scoping, inference, assignment, etc.
The first cool part of all of this is what Java refers to as SAM methods (single abstract methods). Essentially what that means is that any interface or abstract class defining a single abstract method can be automatically converted to a closure. Because anonymous classes have been so heavily used throughout the history of Java, SAM types are prevalent everywhere: Runnable, Comparable, Closable, listeners, handlers, etc. Even types in your own APIs are SAM types.
For example, let’s say you have a callback handler:
public interface Callback { public void handle(Data data); } |
You may be using this callback as a parameter to a method such as an async invocation.
public class AsyncFactory { public static void invoke(Data input, Callback callback) { // run in background thread and invoke callback with result callback.handle(response); } } |
Now, you can invoke this using a closure simply via:
AsyncFactory.invoke(data, #{ data -> System.out.println("Response: " + data); }); |
You can even make assignments such as:
Callback cb = #{ response -> … }; AsyncFactory.invoke(data, cb); |
SAMs make legacy code easy to use with closures and greatly simplifies boilerplate code. Another part of assigning lambda expressions is the ability to reference existing methods (such as utility methods or instance methods). There has probably been a time or two that you have wanted access to a method to pass it to another method, but did not want to use reflection or create some anonymous function. Well, with project lambda they exist now. Check these out:
public class Processor { public void static process(Data response) { … } } AsyncFactory.invoke(data, #Processor.process); |
That’s it. The process method will now be wrapped as a SAM and lambda expression and passed into the method as a Callback instance. This is really nice and efficient sugar. You can also reference instance methods (ie: #myInstance.method) or even reference overloaded methods with specific parameter types (ie: #Processor.process(Data), #Processor.process(String), etc). This functionality is still being flushed out by the committee.
The coolest feature, however, and what excites me the most around architecture and frameworks are defender methods. At the core, defender methods sound boring, but under the covers, they open doors to all kinds of improved coding and modularity. The initial purpose around defender methods is to allow a way for Java to update the collection APIs for support with closures without breaking almost every framework on the planet, since many depend on collections. For example, if Java adds a new method to the Collection interface, any framework with implementations of Collection will fail to compile. Java obviously does not want this type of incompatibility. Their solution: defender methods to allow default implementations in interface methods. This allows frameworks or Java to add new API methods by defaulting to a given implementation. Thus, libraries that do not update will get the default implementation. The end result is that the collection APIs get updated and no libraries get broke. An example is that Java wanted to enhance the collection APIs using the Collections utility class and apply methods via lambda expressions directly to the actual collection APIs. For example, rather than solely have a Collections.sortBy method taking both a list and extractor, it is easier to just place the sortBy method on the actual list interface and default to the Collections implementation (plus it makes it easier to lookup available functionality on just the class rather than also looking at the Collections utility class):
public interface List<T> extends Collection<T> { … public extension <U> void sortBy(Extractor<T, U> extractor) default Collections.<T, U>sortBy; } |
This tells the compiler that the default implementation of sortBy on a List will use the Collections.sortBy method unless an implementing class explicitly defines its own implementation. In essence, the List interface has now been updated, but implementing classes have not, nor need to, change. This really makes ensuring backwards compliance in any framework simplified while at the same time adding significant improvements. If you are curious why the body cannot just be defined inlined, see the documentation and the JSR forums. It revolves around the notion that interfaces are just interfaces without bodies of code and they wanted to keep that definition in tact.
If you think deeper about these default methods, you may see the opening to modules or the mixin design pattern. Actually, that was another focus or point of implementing this type of scenario. Java lives by the rule that extending multiple classes creates a complex system and hierarchy. As a result, Java does not let you extend two different classes. However, I’m sure at some point everyone has wanted that functionality, especially if dealing with delegation patterns or existing libraries that you want to both extend the third party class and an abstract helper class. All of these scenarios are not possible in Java. They are, to a point, available in some other newer languages, such as Ruby. Even then, Ruby also has the restriction that every class has one and only one parent class. What Ruby has that Java does not have is modules or mixins. Ruby allows you to include another class inline with the existing class so that it gets all of its methods. The result is that classes still have a strict hierarchy, but they also have modules for enhanced functionality with a clear separation. Let’s walk through an example.
Let’s say you are relying on some third party framework and want to extend a particular class to add a specific use case:
public class MyHandler extends ThirdPartyHandler { public void handleData(Data data) { ... } } |
Let’s also assume you have another class that does file operations in a default and consistent manner:
public class FileProvider { public void save(String filename) { …. } } |
In this system, there is no direct way to extend both ThirdPartyHandler and FileProvider. Instead, you have to copy the methods into MyHandler from FileProvider and delegate to them (or generate code or any number of other tricks). However, this quickly breaks down since the hierarchies are inconsistent, collisions occur, code is less readable, and updates to FileProvider many not propagate through. To get around this, we can use the new defender methods to create an interface that has default method implementations.
public interface FileProvider { public extension void save(String filename) default FileHelper.save; } public class FileHelper { public static void save(String filename) { … } } |
We can now use that FileProvider as an interface (which Java supports multiple of) to extend MyHandler.
public class MyHandler extends ThirdPartyHandler implements FileProvider, OtherProvider { … } |
Our new handler now extends the third party handler and also has the default implementations from FileProvider. No more delegation required, our hierarchy is consistent and concise, and any updates to FileProvider flow into MyHandler properly. We now have mixins in Java!
The coolest places I see this being heavily adopted and used by frameworks is around utility methods or separation of concerns. For example, Java has moved several of the Collections utility methods into the actual interfaces using extension methods. New frameworks can do similar things. It all leads to designing to interfaces, which is always a good thing. In terms of separation of concerns, you can put that logic in their own modules or interfaces and then implement the interface. No need to worry about having to both implement an interface and add the actual method implementations. The file helper example above is a good example since you can define a common set of file-based operations used in all classes without having to worry about extending that particular class. This is a great thing because classes are suppose to define an explicit hierarchy of relationship (Square to Rectangle to Shape to Object). You would not want something like Square to Rectange to ImageHelper to Shape to Object. That leads to confusing hierarchies. Instead, you define the logic in those helper classes as extension methods, since interfaces are meant to provide extra meaning to a class (ie: Comparable, Runnable, etc).
For example, consider another example where we want a consistent means of checking security. Security is a cross-cutting concern and as a result should not be part of the direct class hierarchy. Thus, we can use extension methods to provide the default implementation of security. The class hierarchy does not need to change then..they just need to implement an interface.
public interface Securable { public extension boolean isAllowed() default SecurityContext.isAllowed; } public class HomePage extends AbstractPage implements Securable { … } |
That’s all there is to it. You can now invoke homePage.isAllowed which in turn invokes the static SecurityContext.isAllowed method. We do not have to change the hierarchy to somehow fit SecurityContext into the class structure…we simply design to interfaces. If a particular instance wanted to override that functionality, they simply implement the method:
public class UserPage extends AbstractPage implements Securable { public boolean isAllowed() { if (user.isLoggedIn()) { return user.isAllowed(); } else { return SecurityContext.isAllowed(); } } } |
This type of development really opens the door to several new enhancements and opportunities in today’s and tomorrow’s frameworks. Several new and popular languages like Ruby have this functionality and it is being heavily used to improve libraries. Despite JDK 8 being unavailable for a few years still, it is best to begin thinking about how mixins in the future might affect today’s frameworks to know tomorrow how to implement when they do become available. For more information, see the JSR documentation or see how other languages have used mixins. They are not always one-to-one comparisons with how Java is doing them, but the underlying point is still there.
As one last cool part of these expressions, consider this example straight from project lambda’s documentation:
Create an extractor used to extract a given property from a given object and then use that extractor to sort the underlying list.
interface Extractor<T,U> { public U extract(T t); } public void<T, U extends Comparable<? super U>> sortBy(Collection<T> collection, Extractor<T, U> extractor); |
Let’s start with how today would look:
Collections.sortBy(people, new Extractor<Person, String>() { public String extract(Person person) { return person.getLastName(); } }); |
Now use a lambda expression to apply the sort, rather than an anonymous class:
Collections.sortBy(people, #{ Person p -> p.getLastName() }); |
Shorten that expression using automatic inference:
Collections.sortBy(people, #{ p -> p.getLastName() }); |
Shorten that expression by just referring to the actual last name method since that is all the expression is doing:
Collections.sortBy(people, #Person.getLastName); |
Using defender methods, we can simplify that to just the following since List.sortBy defaults to Collections.sortBy:
people.sortBy(#Person.getLastName); |
This reads much simpler, is much less to write, and just plain better. You can see why now this project really excites me. Unfortunately we still have to wait until late 2012 for this to come along :(

Leave a Reply