Lambda expressions in Java deal with functional programming. It is an introduction to functional programming in Java. Lambda expressions were introduced in Java 8 version. They were introduced to provide implementations to functional interfaces and also provide a simpler way of working with functional interfaces.
What is a Functional Interface?
An interface is termed to be a functional interface if it has exactly one abstract method in it. But, it can have any number of static or Object
class methods. There are some pre-defined functional interfaces in Java, like Runnable
, Comparable
, ActionListener
, etc. Functional interfaces are important to enable the functional programming in Java.
Example of a functional interface:
@FunctionalInterafce // Annotaion public interface Store { void show(); // public abstract method by default }
The annotation used here is to give information to the compiler that it is a functional interface. In this case, the compiler will throw an error when more than one method will be added to the functional interface. Specifying the annotation is totally optional.
The method in the functional interface is by default a public abstract method.
Working of Lambda Expression
Lambda expressions are considered to be anonymous functions that do not belong to any class. They provide functionality to the functional interfaces by providing implementation to the abstract method in them.
Let’s see the basic technique used to implement the abstract method of a functional interface before Lambda Expressions were introduced.
Creating a class to implement the functional interface Store:
class BookStore implements Store { public void show() { system.out.println(“This is a Book Store”); } } public class LambdaDemo { public static void main(String[] args) { Store s = new BookStore(); s.show(); } }
Below is the output, after we run the above program:
This is a Book Store
The class defined here is only created to give an implementation to the functional interface Store. This is treated as a redundant code. Therefore, we can remove this and provide the implementation to the interface Store inside the main class itself. Let’s see how we can do this;
public class LambdaDemo { public static void main(String[] args) { Store s = new Store() { @Override public void show() { System.out.println("This is a Book Store"); } }; s.show(); } }
Here we can see, an instance to the interface has been created and an implementation to its method has been provided at the time of creating the instance. Note that, instances to interfaces are not possible; actually it is creating an instance to an anonymous class.
This code here is treated as an inner anonymous class by Java. So, there is an anonymous class that is still getting created inside the main class.
To further optimize this code, Lambda Expression was introduced in the Java 8 version.
Let’s see how we can simplify the code using Lambda Expression.
public class LambdaDemo { public static void main(String[] args) { Store s = ()-> { System.out.println("This is a Book Store"); }; // Or can also be written like this if it is a single statement // Store s = ()-> System.out.println("This is a Book Store"); s.show(); } }
Therefore, the syntax for a Lambda Expression is:
([parameters list]) -> { body };
The arrow operator was introduced specially for Lambda Expressions. We have seen how the implementation of the functional interface was simplified using Lambda Expression.
The method inside the Store interface has no parameters or return type. What if there are parameters and a return type to the show
method?
Lambda Expression with Parameters and a Return type
Let’s see how we can write a lambda expression for methods having parameters and return types.
Modifying the abstract method to add parameters and a return type:
@FunctionalInterface interface Store { int show(String bookName, String authorName); }
Modifying Lambda Expression to define the implementation of this method:
public class LambdaDemo { public static void main(String[] args) { Store s = (bookName, authorName) -> { System.out.println("The Book Name is " + bookName); System.out.println("The Author Name is " + authorName); return 100; }; int price = s.show("Healthcare", "Carry"); System.out.println("The Price is " + price); } }
After running the above program, you will see the below output;
The Book Name is Healthcare The Author Name is Carry. The Price is 100
You might have noticed, there are not data types mentioned for the parameters in Lambda Expression. Yes, there is no need to specify the type, for parameters in Lambda Expressions; you can simply use the name of the parameters.
Therefore, from the above examples, we can say that the Lambda Expression can be treated as an object that can be assigned to variables and passed around.
Variables in Lambda Expression
Lambda Expressions can access and use variables declared outside it’s body. The variables that it can use are the:
- Local variables
- Static variables and
- Instance variables
Let’s see an example for this:
@FunctionalInterface interface Store { void show(); // public abstract method by default }
public class LambdaDemo { int instanceVar = 10; // Instance variable static int var = 20; // Static variable public static void main(String args[]) { Store s = () -> { int localVar = 30; System.out.println(localVar); System.out.println(var); LambdaDemo e = new LambdaDemo(); System.out.println(e.instanceVar); }; s.show(); } }
Below output will be displayed, after successful execution of above program;
30 20 10
Based on the above examples do try out your version of creating and experimenting with Lambda Expressions. Good Luck!