chapter 15
Chapter 15: Lambda Expressions in Java
Introduction to Lambda Expressions
Lambda expressions are a key feature of Java, introduced to facilitate functional programming.
Contains two core constructs: Lambda expressions and Functional Interfaces.
Definition: A lambda expression is an anonymous method, effectively an unnamed function used to implement the defined method of a functional interface.
Lambda expressions can also be referred to as closures.
Functional Interfaces
Definition: A functional interface is an interface that contains exactly one abstract method, defining the intended purpose and representing a single action.
Example: The
Runnableinterface is a functional interface because it has only one method:run(), representing its action.A lambda expression can only be utilized in a context where its target type is defined by a functional interface.
Functional interfaces are sometimes known as SAM types (Single Abstract Method).
Syntax and Structure of Lambda Expressions
Lambda expressions introduce a new syntax and operator in Java denoted by ->.
The structure consists of two parts:
Left Side: Specifies parameters required (can be empty if none).
Right Side: Contains the action to be performed.
The operator can be read as "becomes" or "goes to." There are two types of lambda bodies:
Single Expression
Block of Code
Example of a simple expression:
() -> 123.45(equivalent to a method that returns123.45).Example with Math:
() -> Math.random() * 100, obtaining a pseudo-random value multiplied by 100.
Working with Parameters
When parameters are involved, they are listed on the left of the operator:
Example:
(n) -> (n % 2) == 0returns true ifnis even.
Type inference allows parameters to be defined implicitly based on context.
Lambda expressions can have multiple parameters as needed but need to declare types explicitly if they are more than one.
Usage of Functional Interfaces
Lambda expressions need to be assigned to a functional interface reference, establishing a target type context.
Example:
MyNumber myNum; myNum = () -> 123.45;This forms an anonymous class that implements the functional interface, allowing lambda behavior.
When
getValue()is invoked, it executes the lambda expression returning the specified value.
Complex Lambda Examples
Type Inference in Lambda: When a type is not specified, it can often be inferred:
Example:
(n) -> (n % 2) == 0allows type inference based on method usage.
When declaring types, all parameters must have types specified; mixing inferred and explicit type specifications is illegal.
Example legal:
(int n, int d) -> (n % d) == 0is valid.
Block Lambda Expressions
Block lambdas consist of a block of code enclosed in braces (
{}).Allows significant versatility, including variable declaration, loops, and conditional statements.
Must return values explicitly using the
returnstatement.Example: A block lambda reversing a string.
A block lambda has more complexity and utility over expression lambdas.
Handling Exceptions in Lambda Expressions
Lambda expressions can indeed throw exceptions; however, checked exceptions must be compatible with the
throwsclause of their functional interface's abstract method.Example: A block lambda calculating an average, throwing
EmptyArrayExceptionfor a zero-length array.
Variable Capture in Lambda
Local variables captured in lambdas must be effectively final.
Modifying the local variable after its assignment would disallow its use in lambda expressions.
Example: Attempting to modify an effectively final variable inside a lambda leads to compilation errors.
Method References
Method references allow referencing methods directly without executing them.
This relates to lambda expressions, as both require a functional interface context.
Various methods of referencing include referencing static methods, instance methods, and using generics.
Predefined Functional Interfaces
Java provides several built-in functional interfaces within the
java.util.functionpackage, reducing the necessity to define custom interfaces.Example Implementation: The
Functioninterface can compute factorials and other operations without needing distinct functional interfaces every time.
Conclusion
The chapter effectively introduces and elaborates on lambda expressions, functional interfaces, their syntax, operational examples, and the handling of exceptions in the context of Java programming. The application of lambda expressions integrates functional programming techniques, making Java a more versatile and modern programming language.