Lambda Expressions are the most remarkable feature added to the Java platform with Java 8. It’s specified in JSR 335 and JEP 126. The very need for this feature is to gain some of the capabilities supplied by functional programming. The main idea behind this concept is to be able to parametrize the functions for subsequent executions of them.

Till Java 8, this could already be simulated via the use of anonymous inner classes with some design patterns like command pattern and functors. However, the adoption of lambda expressions gave way to the direct use of this concept.

1. What is a Lambda Expression?

A lambda expression is a piece of code that is giving an alternative way to the anonymous class to pass the function as a parameter to other subsequent flows of code such as methods, constructors, etc… In this approach, a function can be referenced with a variable and passed as a reference to be executed in a subsequent flow of code execution.

The structure of a lambda expression is as follows; it is formed of some arguments, followed by an arrow and that’s followed by a code block.

Lambda Expression

Lambda Expression

2. Type of Lambda Expressions; Functional Interfaces

A lambda expression is identified by a special single-method interface called Functional Interface. A functional interface is the target type that’s determined by the compiler and used as the type of the reference to the lambda expression.

This binding of a lambda expression to a functional interface is determined from the context of the lambda expression. That means, the binding of a lambda expression to a target type can take place in different contexts such as variable declarations, method arguments, constructors, etc.; and from this binding, the compiler finds the target type, which is a functional interface, and infers the types of the parameters used in the lambda expression according to that functional interface.

A functional interface can be marked with an informative annotation @FunctionalInterface that can be used to inform other developers.

Let’s do a simple example to understand it well.

Think that we want to lowercase or uppercase a text based on a condition.

It will be a dynamic evaluation so we can abstract the operation.

By leveraging the lambda expressions we can do it as following:

Here is the lambda expressions for case operations:

t -> t.toUpperCase();
t -> t.toLowerCase();

By looking at the code above, we see that there is a parameter t; we do not know its type, and in the code block of the expression, the methods of t, which are toUpperCase and toLowerCase, are called.

To be able to pass these expressions to somewhere, we have to declare a functional interface; with that single-method interface, the compiler will be able to infer the type of t:

public interface CaseOperation {
    String operate(String text);
}

Then we can write our main code as such:

public void printWithCaseOperation(String text, CaseOperation operation){

    System.out.println(operation.operate(text));    
}

public void mainCode(){

    if(upperCaseEnabled){
        printWithCaseOperation("Hello Lambda!", t -> t.toUpperCase());
    } else {
        printWithCaseOperation("Hello Lambda!", t -> t.toLowerCase());
    }
}

Here, when we call the method printWithCaseOperation with a lambda expression as its second parameter, the compiler infers that the method’s second parameter is of type CaseOperation and, so is also of the lambda expression’s type, too.

3. Some Internals

At this point, let’s watch this video to listen to the internals of lambda expressions.

For whom needs some speed, I will summarize it, you’re welcome:

  • We need lambdas basically since of; parallel friendly APIs and less code with the usage of closure-like functional programming capabilities.
  • Lambdas are not a new function type in the VM-level; it’s mostly about compiler level.
  • The compiler does a great job for us by transforming our lambdas into the form of a related defined functional interface. In other words; the compiler infers our lambdas as functional interfaces.
  • When the compiler sees the lambda expression, it simply creates a static method from the resolved related functional interface and in the invocation time, the VM executes that method by calling invokedynamic which is an invocation mode introduced in Java SE 7.

4. Lambda Syntax

Java Lambda Expressions have a basic structure as drawn in the diagram above. Besides this, some inferences can be made automatically by the compiler for us. When writing lambda expressions these compiler inferences directs us to write less code.

#java #programming #developer

Java Lambda Expressions
3.10 GEEK