Contexts for Defining Lambda Expressions – Functional-Style Programming
13.14 Contexts for Defining Lambda Expressions
In this section, we summarize the main contexts that can provide target types for lambda expressions and method references.
Declaration and Assignment Statements
Ample examples of defining lambda expressions and method references in this context have been presented throughout this chapter. As we have seen earlier, the target type is inferred from the type of the assignment target—that is, the functional interface type being assigned to on the left-hand side of the assignment operator.
DoubleFunction cToF = x -> 1.8 * x + 32.0; // double -> double
ToIntFunction<String> lenFunc1 = s -> s.length(); // String -> int
ToIntFunction<String> lenFunc2 = String::length; // String -> int
lenFunc1 = s -> Integer.parseInt(s); // String -> int
lenFunc2 = Integer::parseInt; // String -> int
Method and Constructor Calls
We have seen several examples where a lambda expression is passed as an argument in a method or constructor call. The target type is the functional interface type of the corresponding formal parameter.
List<Integer> numbers = Arrays.asList(1, 2, 3);
numbers.forEach(i -> System.out.println(i)); // Target type: Consumer<Integer>
numbers.forEach(System.out::println);
Expressions in return Statements
The expression in a return statement can define a lambda expression (or a method reference) whose target type is the return type of the method. The method below returns a function of type int -> int:
static IntUnaryOperator createLinearFormula(int a, int b) {
return x -> a * x + b; // int -> int
}
// Client code:
IntUnaryOperator y = createLinearFormula(10, 5); // 10 * x + 5
y.applyAsInt(2); // 25
Ternary Conditional Expressions
For lambda expressions defined in a ternary conditional expression, the target type is inferred from the context of the ternary conditional expression.
In the first ternary conditional expression below, the target type for the lambda expressions that are operands is inferred from the target of the assignment statement, which happens to be an IntUnaryOperator interface.
int ii = 10;
IntUnaryOperator iFunc1 = ii % 2 == 0 ? i -> i * 2 : j -> j + 1; // int -> int
iFunc1.applyAsInt(4); // 8
//IntUnaryOperator iFunc2 = ii % 2 == 0 ? i -> i * 2
// : s -> Integer.parseInt(s); // Compile-time error!
In the second ternary conditional expression above, the code does not compile because the type String -> int of the lambda expression that is the second operand is not compatible with the type int -> int of the assignment target.