Lambdas in Java 8

Lambdas in Java 8

Java 8 has been out for a while now, and there are a lot of great posts about all the new features, but I’m preparing an introduction for a team that just started to use Java 8, so I thought I could just as well publish my notes as a blog post.

Lambdas are actual “just” another way of creating anonymous inner classes, in the pre Java 8 world, we had to write:


1
2
3
4
5
6
7
8
JButton jButton = new JButton();
       
jButton.addActionListener(new ActionListener() {
  @Override
  public void actionPerformed(ActionEvent e) {
    System.out.println("Button pressed with id: " + e.getID());  
  }
});

Where this section is the creation of the anonymous inner class.


1
2
3
4
5
6
new ActionListener() {
  @Override
  public void actionPerformed(ActionEvent e) {
    System.out.println("Button pressed with id: " + e.getID());
  }
}

But because the ActionListener is a single method interface, in Java 8, the type declaration, parentheses around the parameters, the curly braces and return keyword, all are now optional.
So instead, the same code can be written as:


1
2
JButton jButton = new JButton();
jButton.addActionListener(e -> System.out.println("Button pressed with id: " + e.getID()));

For this to be possible, the interface must be a single method interface. In this case, the ActionListener.

Single method interface

A said before, to be able to use the lambda expression, it must be able to be mapped to an interface with only one method declared.

Parameters

The parameters in the lambdas expression must match does in the interface method. Both in number and type, but remember that auto boxing, Integer matches to int.
The compiler uses type inference to match the type of the parameters to the methods, that is, it checks the method declaration in the interface and infer them in the lambda expression.
You can also specify the type at declaration, sometimes that might be necessary if the compiler can’t infer the type.


1
(float a, float b) -> 2*a*b + Math.pow(a,b);
Zero parameter

If the method has zero parameters, this is written as ().


1
 () -> System.out.println("Zero parameters");
Single parameter

A single parameter can be written with or without parentheses.


1
2
3
4
5
(para) -> System.out.println("One parameter " + para);

// Or

para -> System.out.println("One parameter " + para);
Multiple parameters

Are written as a comma seperated list within the brackets.


1
 (para1, para2) -> System.out.println("Several parameters " + para1 + para2);

Return types

Return type in the lambda expression must match the one in the interface method (same here, autoboxing will kick in).

Function body

The body of an lambdas expression is the code given after the ->. It can consist of several lines of code and can return a value. If you have a single line, you can omit the
return keyword.


1
2
3
4
5
6
7
8
9
// Single line
(float a, float b) -> 2*a*b + Math.pow(a,b);

// Multiple lines, must be enclose with in {}
(float a, float b) -> {
  float sum = 2*a*b;
  sum += Math.pow(a,b);
  return sum;
}

Lambdas vs. anonymous inner classes

A big difference between Lambdas and anonymous inner classes, are that the former will be created as an class at compile time.
And for each new inner class, it will generate a new class file when compiling.
You can study this by looking at your class files, you will see the ugly files named MyClass$1.class.

But if you instead use lambdas, these ugly files are gone, how come?

Well it’s because for lambdas the compiler and and JVM is using the something called invoke dynamics, which in very short means that the actual implementation is compiled in runtime instead of in compile time, as with anonymous inner classes. If you want to read more about this, you can do it here From Lambdas to Bytecode by Brian Goetz

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.