Your First Lambda Expression:
There is a general usage in Swing library: we need a action listener to response a user operation.
Before Java 8, we have to create a new inner class which implements ActionListener interface and overide its unique method actionPerformed
like the following code:
1 | button.addActionListener(new ActionListener() { |
There are two problem:
1. So many template codes
2. The codes are not easy to read without expressing the purpose of the programmers
With Java 8, we can create a lambda expression:
1 | button.addActionListener(event -> System.out.println("button clicked")); |
Instead of passing in an object that implements an interface, we are passing in a bock of code : a function without a name.
In this code, we do not need to explicitly declare the type of event. In Lambda Expression, java compiler can infer the type of variable event
from the context.
Note: For the sake of readability and familiarity, you have the option to include the type declarations, and sometimes the compiler
just can’t work it out!
How to Spot a Lambda in a Haystack
The following code are five forms of lambda expressions as an example:1
2
3
4
5
6
7
8Runnable noArguments = () -> System.out.println("Hello World");
ActionListener oneArgument = event -> System.out.println("button clicked");
Runnable multiStatement = () -> {
System.out.print("Hello");
System.out.println(" World");
};
BinaryOperator<Long> add = (x, y) -> x + y;
BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y;
Using Values, Not Varialbes
When you want to pass a varible outside the anonymous method into the method, you should declared the variable as final. Making a variable final means that you can’t reassign to that variable.
1 | final String name = getUserName(); |
For lambda expression, although you do not need to set the outside variable as final, but you can still not change the value. If you changed, there will be an complie error.1
2
3
4
5
6
7interface Formula {
double calculate(int a);
default double sqrt(int a) {
return Math.sqrt(a);
}
}
Default Methods for Interfaces
Java 8 enables us to add non-abstract method implementations to interfaces by utilizing the default
keyword. This feature is also known as Extension Methods. Here is our first example:
1 | interface Formula { |
Functional Interfaces
A functional interface is an interface with a single abstract method that is used as the type of a lambda expression.
How does lambda expressions fit into Javas type system? Each lambda corresponds to a given type, specifibd by an interface. A so called functional interface must contain exactly one abstract method declaration. Each lambda expression of that type will be matched to this abstract method. Since default methods are not abstract you’re free to add default methods to your functional interface.
To ensure that your interface meet the requirements, you should add the @FunctionalInterface
annotation. The compiler is aware of this annotation and throws a compiler error as soon as you try to add a second abstract method declaration to the interface.
Example:1
2
3
4@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}
Keep in mind that the code is also valid if the @FunctionalInterface annotation would be ommited.
Interface name | Arguments | Returns | Example |
---|---|---|---|
Predicate |
T | boolean | Has this album been released yet? |
Consumer |
T | void | Printing out a value |
Function |
T | R | Get the name from an Artist object |
Supplier |
None | T | A factory method |
UnaryOperator |
T | T | Logical not (!) |
BinaryOperator |
(T, T) | T | Multiplying two numbers (*) |