August 14, 2012

‘At First Sight’ With Closures in Java



The intent of this Online Tutorial on Java is to give a high level overview of the upcoming Lambda Project, which is being developed upon JSR-335 (Second Early Draft Review of JSR-335 is closed in June, 2012). The Lambda Project is going to be a part of Java SE 8 (Java 1.8), which is set to be released in 2013.



The JSR-335 introduces Closures in Java. The Closures are quite common in most of the popular languages like C++ and C#. Closures let us create function pointers and pass them as parameters; also the methods will be able to enclose the surrounding context as a snapshot so that it can be passed along with the method. In this article we will go through the Java 8 features, and introduce ourselves with the Lambda Expressions. I have tried to put some sample example programs codes to explain the concept and the syntax, better.

Java Programming Language provides us with the concepts of Interfaces that are capable of defining abstract methods only. Interfaces define an API and they expect users or vendors to provide implementations for their methods.


Many a times, we do not create separate implementation classes for a given interface. Instead of that we write inline interface implementations, which are also called as Anonymous Inner Classes.

Anonymous classes are used widely. In our day-to-day life we can see their presence in number of libraries. Anonymous classes are majorly used to specify event handlers within the components that generate events. Second major use of Anonymous classes can be seen in multithreaded programs. Many a times, instead of creating dedicated Runnable/Callable implementation, we write Anonymous classes.

As we discussed, an Anonymous class is nothing but an inline implementation of a given interface. Usually, we pass such implementation classes as an argument to a method and then the method will internally invoke methods on the passed implementation class. Hence such interfaces are called as Callback interfaces and their methods are called as Callback methods.

Though, the Anonymous classes are being used everywhere, they have number of problems. First and major issue is with the complexity. These classes make the code bulky and complex. Sometimes, it is also called as a Vertical Problem, because these classes will increase the vertical length of a program. Secondly, they cannot access the non-final members of the enclosing class. They sound confusing in terms of shadow variables and with the behavior the ‘this’ keyword. If an Anonymous class has variable with a name same as that of any member of the enclosing class then the inner variable will shadow the outer member variable. In that case the outer member will be invisible to the anonymous class and it can't even be accessed by mean of the 'this' keyword. The ‘this’ keyword in Anonymous class points to itself and not to the enclosing class.


public void anonymousExample() {
    String nonFinalVariable = "Non Final Example";
    String variable = "Outer Method Variable";
    new Thread(new Runnable() {
        String variable = "Runnable Class Member";

        public void run() {
            String variable = "Run Method Variable";

            //Below line gives compilation error.
            //System.out.println("->" + nonFinalVariable);
            System.out.println("->" + variable);
            System.out.println("->" + this.variable);
       }
    }).start();
}

The output is:

->Run Method Variable 
->Runnable Class Member

The output of this programs shows, how the inner variable has shadowed the outer one and the 'this' keyword refers to the Anonymous class scope only.

Though, they are not meant for this, but the Lambda expressions address almost all of the issues caused by an Anonymous inner class. Before we proceed further to the Lambda expressions, let's have a look at Functional Interfaces.



Functional Interfaces: 

Functional Interface is an interface that has just one method and thus represents a single function contract.

The word ‘single’ occurred in the definition is actually not that simple. The ‘Single’ method can exist in the form of multiple abstract methods that are inherited from superinterfaces. But in that case the inherited methods should logically represent a single method or it might redundantly declare a method that is provided by classes like Object, e.g. toString.

Below examples will help you to understand the concept of functional interfaces clearly.

interface Runnable { void run(); }
// Functional

interface Foo { boolean equals(Object obj); }
// Not functional; equals is already an implicit member

interface Bar extends Foo {int compare(String o1, String o2); }
// Functional; Bar has one abstract non-Object method

interface Comparator {
 boolean equals(Object obj);
 int compare(T o1, T o2);
}
// Functional; Comparator has one abstract non-Object method

interface Foo {int m();   Object clone(); }
// Not functional; method Object.clone is not public

interface X { int m(Iterable arg); }
interface Y { int m(Iterable arg); }
interface Z extends X, Y {}
// Functional: two methods, but they have the same signature


Most of the common callback interfaces are Functional interfaces e.g. RunnableCallable, or Comparator etc. Previously the functional interfaces used to be called as SAM (Single Abstract Method) Types.



Lambda Expressions:

As we have discussed above, the major problem with the Anonymous classes is the Vertical Problem. The Lambda Expressions are nothing but Anonymous classes but their structure is more lightweight and shorter. The Lambda expressions are like methods. They have a list of formal parameters and a body-an expression block-expressed in terms of those parameters.


(String s)-> s.lengh;

() -> 43;

(int x, int y) -> x + y;


In the above examples of Lambda expressions, the first expression takes String variable as an argument and then returns length of the String. Second one doesn’t take any parameter and returns 43. Finally, the third one takes two integers x, and y and returns their addition.

After facing lots of issues, finally, I was able to run my very first Lambda expression example with the help of Java SE 8’s preview edition.

public class FirstLambdaExpression {
    public String variable = "Class Level Variable";

    public static void main(String[] arg) {
        new FirstLambdaExpression().lambdaExpression();
    }

    public void lambdaExpression(){
        String variable = "Method Local Variable";
        String nonFinalVariable = "This is non final variable";

        new Thread (() -> {
            //Below line gives compilation error
            //String variable = "Run Method Variable"

            System.out.println("->" + variable);
            System.out.println("->" + this.variable);
       }).start();
    }
}

The output is:

->Method Local Variable 
->Class Level Variable


Comparing the output of the Anonymous example (seen sometimes back) with the current one, we can clearly say that writing Anonymous classes in the form of lambda expressions solves the issues with the variable visibility and with the behavior of 'this' keyword. Look at the commented line in the program, the lambda expressions are not allowed to create shadowing variables.

The general syntax of Lambda expressions consists of an argument list, the arrow token ‘->’ and finally the body. The body can simply be an expression (single statement) or a block of multiple statements. If the body is an expression then it will be evaluated and returned and if it is a block then it will be evaluated similar to method blocks, and then ‘return’ statement is required to return a result. The break and continue are illegal at the top-level but permitted within the loops.

The particular syntax has been chosen because it is already made common by the languages like C# and Scala. The syntax is basically designed so that it addresses the complexity of Anonymous classes. For the same purpose it is also quite flexible, e.g. if the method body is a single expression then neither the blocks nor the return statement is required. The outcome of the expression is itself treated and returned as a response from that method. This kind of flexibility also helps in keeping the methods short and simple.

The Lambda expressions are used as anonymous classes and hence they can be flexibly used within other blocks or within other lambda expressions (nested lambda expressions).


//Lambda expression is enclosed within methods parameter block.
//Target interface type is the methods parameter type.
String user = doSomething(() -> list.getProperty(“propName”);

//Lambda expression is enclosed within a thread constructor
//target interface type is contructors paramter i.e. Runnable
new Thread (() -> {
    System.out.println("Running in different thread");
}).start();


If you look carefully at lambda expressions, you will see that the target interface type is not a part of the expression. The compiler infers the type of lambda expressions with the help of surrounding context.

The lambda expressions cannot exist without a target type, and they are compatible with every possible target type. Compiler performs a check whether the types used by the lambda expressions are compatible with the method signature of the target type. When a lambda expression is targeting an interface, below are the things that are required to make the compiler ‘happy’:
  • The interface should be a functional interface.
  • The number and the type of parameters should be the same as that of the target interface’s functional method.
  • The return type of the expressions should be compatible with that of the interface’s functional method.
  • The exceptions thrown by expressions should be compatible with the exceptions thrown by the interface’s functional method.
As the compiler is already aware of the Target type and its method parameters, the lambda expressions are allowed to skip the parameter types in the declaration.


Comparator c = (s1, s2) -> s1.compareToIgnoreCase(s2);



Moreover, if the target’s functional method accepts only one parameter (true in most of the cases), then the parenthesis surrounding the parameters becomes optional.


ActionListenr listenr = event -> event.getWhen();



This also answers one very obvious question: Why the Lambda expressions do not require the method name to be specified?

The answer is: lambda expression work only for functional interfaces, and the functional interfaces have only one method. When we target a lambda expression with a particular functional interface, the compiler is already aware of the signature of the functional method and it can easily check for the matching signature in the given expression. On the same lines the methods argument types can also be skipped. It would have been a redundancy, if we had to specify method names, and argument types in the expressions.

This kind of flexible syntax helps in avoiding the Vertical Problem without introducing a Horizontal Problem (lengthy statements).

The Lambda expressions are said to have context-dependent syntax, but these are not the first one to have that. The generic method invocations and the Java SE 7’s newly added diamond operators are also have this concept, where the type is inferred by the surrounding context.

Inferring the target type becomes complex in the case when lambda expressions are method parameter.


void invoke(Runnable r) {r.run()}
void  Future invoke(Callable r) {return c.compute()}
//above are two methods, both takes parameter of type functional interface

Future s = invoke(() ->"Done"); //Which invoke will be called?



The answer of above is the invoke method with a Callable argument. In such cases the compiler decides the target type with the help of overload resolution and type argument inference. When there are more than one applicable overloaded methods, the compiler also checks the compatibility of the lambda expressions with the corresponding target type. In simple words the above call to the invoke method expects a response and there is only one method returning a response.

A Lambda expression can be explicitly casted to a specific target type, provided that, it is compatible with the corresponding target. Have a look at the below program, where I have created three different Callable implementations and passed them as arguments to the 'asList' method. While doing so, I have added a cast for all of the three instances.


public class FirstSightWithLambdaExpressions {
    public static void main(String[] args) {
        List list = Arrays.asList(
            (Callable)()->"callable 1",
            (Callable) ()->"callable 2",
            (Callable) ()->"callable 3");
        ExecutorService e = Executors.newFixedThreadPool(2);
        List futures = null;
        try {
            futures = e.invokeAll(list);
            new FirstSightWithLambdaExpressions().dumpList(futures);
        } catch (InterruptedException | ExecutionException e1) {
            e1.printStackTrace();
        }
        e.shutdown();
    }

    public void dumpList(List list) throws InterruptedException,
              ExecutionException {
        for (Future future : list) {
            System.out.println(future.get());
        }
    }
}

As we have discussed before, the Anonymous classes could never access the non-final variables from the surrounding context. But the Lambda expressions bring a little relaxation in these limitations as they are allowed to access effectively final variables from the surrounding. A variable is effectively final if its initial value is never changed.

As of now, the definition of functional interfaces only applies to the interfaces. I tried creating a lambda expression targeting an abstract class with only one abstract method, but it thrown a compilation error.  As per the JSR-335, the future version of lambda expressions may support the Functional Classes.



Method References:

Method reference is used to refer to a method without invoking it.

The Lambda expressions allow us to define an anonymous method and treat it as an instance of functional interface. Method references allow us to do the same thing, but with the existing methods. Method References are similar to Lambda expressions, that they require a target type, but instead of providing implementation of a method, they refer to a method of an existing class or object.


System::getProperty
"abc"::length
String::length
super::toString
ArrayList::new


The above statements show the general syntax for Method and Constructor References. Here we see a new operator ‘::’ (double colon) has been introduced. I am not yet clear with the exact name for this operator, but the JSR refers it as a Method Reference Delimiter and Wikipedia page refers it as a Scope Resolution Operator. For our reference, within the scope of this tutorial we will simply refer it as a delimiter. 

The target reference (or a receiver) is placed before the delimiter and name of the method is provided after the delimiter. This forms an expression, which is able to refer a method.  In the last statement of the above code, the method name is ‘new'. This expression is referring to the constructor of ArrayList (the constructor references are discussed in the next section). The implicit lambda expression takes LHS of the delimiter as a Target Type and at the RHS side the actual implementation of the referred method or constructor is replaced at runtime.   

Before we go deeper into this, I want to show you the power of method references. I have created a simple sorting program for an array of type Employee.


import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

public class MethodReference {
    public static void main (String[] ar){
        Employee[] employees = {new Employee("Nick"), new Employee("Robin"), new           Employee("Josh"), new Employee("Andy"), new Employee("Mark")};
        System.out.println("Before Sort:");
        dumpEmployee(employees);
        Arrays.sort(employees, Employee::myCompare);
        System.out.println("After Sort:");
        dumpEmployee(employees);
    }

    public static void dumpEmployee(Employee[] employees){
        for(Employee emp : Arrays.asList(employees)){
            System.out.print(emp.name+", ");
        }
        System.out.println();
    }
}

class Employee {
    String name;

    Employee(String name) {
      this.name = name;
    }

    public static int myCompare(Employee emp1, Employee emp2) {
        return emp1.name.compareTo(emp2.name);
    }
}

The output is:

Before Sort: Nick, Robin, Josh, Andy, Mark,  
After Sort: Andy, Josh, Mark, Nick, Robin,

Nothing special happened with the output, but the real crux is happening with the call to ‘Arrays.sort’ method. Employee is a very simple class with a single attribute as ‘name’ (I know my encapsulation is going for a toss, but to keep the code shorter, I take the excuse). The static method ‘myCompare’ takes two employees and returns the comparison of their names.

In the ‘main’ method I have created an Array of different employees and passed it as a first parameter to ‘Arrays.sort’ method. The second parameter to ‘sort’ is the method reference expression (Employee::myCompare). The Employee denotes the Class Type and after the delimiter is the name of the method.

Wait a minute; as per the Java-Doc the sort method takes Comparator as a second parameter, but we are passing a reference to Employee’s static method.  The most important thing to note here, is neither my Employee implements a Comparable nor I have written a separate Comparator class, but still the output is just perfect.

Let's see what happened here. The ‘Arrays.sort’ method expects an instance of Comparator, which is a functional interface that means it has only one method: ‘compare’. Here we can also pass a Lambda expression, which provide an implementation to its functional method. But in our example we already have a comparison method in the Employee class. Though, the name of the method is different, the list of parameters and the return type is the same. Hence, we can create a reference to this method and pass it as a parameter to the ‘sort’.

When there are multiple methods with the same name, the compiler looks at the target type and chooses the best match. To get this clear let's go through an example.

public static int myCompare(Employee emp1, Employee emp2) {
 return emp1.name.compareTo(emp2.name);
}

//Another method with the same name as of the above.
public static int myCompare(Integer int1, Integer int2) {
 return int1.compareTo(int2);
}

I have created two different arrays to be sorted. First is the same Employee array and second is a normal Integer array.

Employee[] employees = {new Employee("Nick"), new Employee("Robin"), 
          new Employee("Josh"), new Employee("Andy"), new Employee("Mark")};
Integer[] ints = {1 , 4, 8, 2, 3, 8, 6};



Now, I am sorting both of the arrays as below.

Arrays.sort(employees, Employee::myCompare);
Arrays.sort(ints, Employee::myCompare);


Here, both of the method reference statements are exactly the same, only the difference is with the arrays we are passing in. Instead of raising an ambiguity flag, the compiler intelligently checks the type of the first argument (Employee or Integer) and as a second parameter expects a method taking two parameters of the first parameter type and then calls the appropriate methods.

Don’t get mislead by the use of static methods. We can create references for instance methods as well. For static methods, we have used Class Name (Employee) before and the method name after the delimiter. In the case of an instance method, the class name will be replaced by an object (Employee Instance) and after the delimiter will be an instance method of that object.

Though, the last example was perfect for our demo context, we have had an overhead of writing a separate method for the Integer comparison. Integer is already a Comparable and provides implementation for the ‘compareTo’ method. Hence, only the below line could have served our purpose.


Arrays.sort(ints, Integer::compareTo);



Did you find something to get confused here?... If not, I will help you.
Here, Integer is name of a class (not an instance like new Integer()) and the ‘compareTo’ method is an instance (non-static) method of Integer. We all know, we cannot call a non-static method without specifying an instance of the class. Then why the above statement is valid?

The answer is: These kinds of statements are allowed for the arbitrary objects of a specific type. Integer is a data type and for data types this kind of expressions are allowed.
If we make the Employee's ‘myCompare’ method non-static and provide expression like Employee::myCompare then compilation will fail with a message: ‘No Suitable Method Found’.


-->

Constructor References:

Constructor Reference is used to refer to a constructor without instantiating the named class.

The newly added, Constructor reference mechanism is yet another game changing addition by Java SE 8. References to constructors can now be created and passed as an argument or assigned to a target type.

In the case of method references, instead of implementing the methods (like the plain lambda expressions), we refer to the existing methods and use them. Similarly, in case of constructor references we can create reference to existing constructors.

In the last section, we have seen the syntax for Constructor reference (ClassName::new), and it is similar to the method references. These constructor reference expressions can be assigned to the targeted functional interfaces.

In the constructor reference expressions, instead of specifying the exact constructor, we just write ‘new’, and a class may have multiple constructors. In that case the compiler checks the type of the functional interface with all of the constructors in the class, and finally chooses the best match.

It was not easy for me to write my first constructor reference program, because, though, I was aware of its syntax, I wasn’t sure about what to do with them and moreover, how to do. Finally, after trying lots of stupid things, there was the 'Eureka..!' time for me. Lets have a look at the below program.

public class ConstructorReference {
    public static void main(String[] ar){
        MyInterface in = MyClass::new;
        System.out.println("->"+in.getMeMyObject());
    }
}

interface MyInterface{
    MyClass getMeMyObject();
}

class MyClass{
    MyClass(){}
}

The output is:

->com.MyClass@34e5307e


-->
Isn’t it seems little strange? The interface and the class have absolutely no connection except that the interface method returns a type of the class.

This example must have sparked another question in your minds (just like it did for me): How to instantiate a class with parameterized constructor? Let’s have a look at the answer in below program.
 
public class ConstructorReference {
    public static void main(String[] ar){
        EmlpoyeeProvider provider = Employee::new;
        Employee emp = provider.getMeEmployee("John", 30);
        System.out.println("->Employee Name: "+emp.name);
        System.out.println("->Employee Age: "+emp.age);
   }
}

interface EmlpoyeeProvider{
    Employee getMeEmployee(String s, Integer i);
}

class Employee{
    String name;
    Integer age;
    Employee (String name, Integer age){
        this.name = name;
        this.age = age;
    }
}

The output is:

->Employee Name: John
->Employee Age: 30

-->
Now, before reaching to the end of this article, lets have a look at the most amazing feature of Java SE 8 and that is Default Methods.

 

Default Methods:

The Java SE 8 is going to introduce a concept of Default Methods. Earlier versions of Java have interfaces with very rigid kind of structures. The interfaces contain Abstract methods and all the non-abstract implementing classes have to provide implementation for those methods, even if the methods are not applicable in the case of any particular Implementing class.
The upcoming version of Java allows Interfaces to have default implementations for its methods. Yes, an interface can have methods with a body attached to it. The implementing classes are not compelled to implement such default methods.

public class DefaultMethods {
 public static void main(String[] ar){
  NormalInterface instance = new NormalInterfaceImpl();
  instance.myNormalMethod();
  instance.myDefaultMethod();
 }
}

interface NormalInterface{
 void myNormalMethod();
 void myDefaultMethod () default{
  System.out.println("-> myDefaultMethod");
 }

}

class NormalInterfaceImpl implements NormalInterface{

 @Override
 public void myNormalMethod() {
  System.out.println("-> myNormalMethod");
 }
}

The output is:

-> myNormalMethod
-> myDefaultMethod

The interface in above example declares two methods, but the implementing class implements only one because the ‘myDefaultMethod’ is marked with ‘default’ modifier and also provides a block of default implementation. Normal overriding rules are applied here, that if a implementing class is providing implementation for the default method then the class’s method would be called.

An interface extending other Interface can Add, Change, or Remove default implementations of the parent’s methods.

interface ParentInterface{
 void initiallyNormal();
 void initiallyDefault () default{
  System.out.println("-> myDefaultMethod");
 }

}
interface ChildInterface extends ParentInterface{
 void initiallyNormal() default{
  System.out.println("now default - > initiallyNormal");
 }
 void initiallyDefault (); //Now a normal method
}
In this example the ParentInterface defines two methods one is normal and other one is a default. The ChildInterface is simply reversing the parent’s method types by changing default method to normal and vice versa.

Let's have a look at the overriding scenarios where the default method behavior is little trickier.

Suppose a class extends a parent C and implements I; and C has a method, which is override-compatible with a default method provided by I. In this case the method in C will be preferred over I’s default method. This holds true even if C’s method is an abstract.

public class DefaultMethods {
 public static void main(String[] ar){
  Interfaxe impl = new NormalInterfaceImpl();
  impl.defaultMethod();
 }
}

class ParentClass{
 public void defaultMethod() {
  System.out.println("->ParentClass");
 }
}

interface Interfaxe{
 public void defaultMethod() default{
  System.out.println("->Interfaxe");
 }
}
class NormalInterfaceImpl extends ParentClass implements Interfaxe{}


The output is:

->ParentClass

In a second case, my class implements two different interfaces and both of them provide default implementation for override-compatible methods. In this case the compiler will shout for ambiguity and the implementing class will have to implement the method and choose between two default implementations. This can be done with the help of ‘super’ keyword as shown below.

public class DefaultMethods {
 public static void main(String[] ar){
  FirstInterface impl = new NormalInterfaceImpl();
  impl.defaultMethod();
 }
}

interface FirstInterface{
 public void defaultMethod() default{
  System.out.println("->FirstInterface");
 }
}

interface SecondInterface{
 public void defaultMethod() default{
  System.out.println("->SecondInterface");
 }
}
class NormalInterfaceImpl implements FirstInterface, SecondInterface{
 public void defaultMethod(){
  SecondInterface.super.defaultMethod();
 }
}


The output is:

->SecondInterface



So guys, we have come to an end of Java Closure Introduction. In this tutorial we have got familiar with the concept of Functional Interfaces and Java Closure; Understood the Java Lambda Expression syntax, the Method Reference and the Constructor Reference. Also, we wrote our First Lambda Expressions Program with other 'Hello World' examples. 

Java SE 8 (Java 1.8) will soon be knocking our doors and I am highly excited to welcome it, because of its really cool features. Though, these features seem to be confusing initially, as the time passes, they will surely become a part of our routine code.

All the best to all of you and please feel free to post your comments.