Functional Interfaces in Java
A Java lambda expression is written with the arrow operator ->, with a dummy parameter on the left and the computing expression on the right.
Why a Lambda Looks Like a First-Class Function
Many learners meet Java lambda expressions and quickly conclude that Java now treats functions the way languages such as Lisp or JavaScript do: as ordinary values that can be stored, handed around, and invoked by name. The conclusion feels natural. A lambda expression is a compact way to write down a function, and it can be assigned to a variable, so it seems reasonable that the variable would then behave like a function.
This section is about why that conclusion is not quite right, and what Java actually does instead. The source raises the question directly: are functions now first-class in Java? Its honest answer is that it is not sure they are, because some things that are possible in other languages are not possible in Java. The misconception is worth taking seriously precisely because the surface of Java lambdas looks so much like first-class functions.
Keep one concrete case in mind as you read. A lambda expression for squaring is assigned to a variable named sqr. The question is whether that variable can then be used the way a function is used. You will return to this case several times.
Reading the Arrow Form
A Java lambda expression is built around a single operator, the arrow written as ->. The arrow is what marks the whole construction as a lambda expression. Everything to the left of the arrow is the dummy parameter for the function, and everything to the right of the arrow is the expression that computes the function's value.
(squaring example, illustrative)
x -> x * x- 1The left side, x, does not hold a value yet. It is a stand-in for whatever input the function later receives.
- 2The arrow separates the placeholder from the description of work to be done with it.
- 3The right side describes the computation. For a squaring function, it multiplies the placeholder by itself.
- x is the dummy parameter: a placeholder that names the input the function will receive
- -> is the arrow operator that marks this as a lambda expression
- x * x is the computing expression that multiplies the placeholder by itself
The word dummy matters. The parameter is not a variable with a value you can read on its own; it is a placeholder that describes the shape of the input. Read the lambda as a recipe: take one input, call it x, and produce x times x.
Tracing a Lambda Assigned to sqr
The source gives a concrete case. The squaring expression can be assigned to a variable named sqr. Follow the steps below to see what the variable actually holds and what happens when you try to use it.
Assigning a lambda to sqr and attempting a call
A squaring lambda is assigned to a variable named sqr. Can the program then write sqr(42) the way it would call a function?
- 1Write the lambda
The expression x -> x * x describes a squaring function using the arrow form: a dummy parameter on the left, a computing expression on the right.
- 2Assign it to a name
The lambda is placed where Java expects a value, in a variable named sqr. Java is strongly typed, so the variable must be declared with a type. An illustrative declaration is: SomeFunctionalType sqr = x -> x * x; where SomeFunctionalType stands in for the functional interface type that the source introduces next.
- 3Attempt the call
Writing
sqr(42)treats sqr like a free-standing function. The source states that Java does not permit this, even though the assignment itself was legal. - 4Identify what is missing
The assignment supplied the expression but not the type that tells Java what kind of value sqr refers to. That missing type information is what makes the call illegal.
The assignment succeeds, but sqr(42) is not permitted. The variable holds a lambda-typed value, not a callable function name.
Why Strong Typing Blocks the Call
The reason sqr(42) fails is strong typing. Java is a strongly typed language, which means that to have a variable named sqr, you must declare that variable and give it a type. The question then becomes: what type fits a value that is a function? The source's answer is a construct called a functional interface. The source names the type that lambda expressions use in Java as a functional interface, and says its role is to supply the type a lambda needs when it is held in a variable or passed around.
Functional interface: the type that lets Java accept a lambda expression as a value. A lambda is written in the arrow form, and the functional interface is the declared type that makes that form legal to store in a variable or pass as an argument.
The arrow tells you how the function is written. The type tells Java what kind of value the name refers to. A plain assignment supplies the first but leaves the second unsettled, and that is why a call written as if sqr were a function has no legal meaning in Java. The details of how a functional interface is declared are the subject of the next section of the source, so this article does not go further into them.
A lambda expression can appear in three places: as an actual parameter passed to a subroutine, as an assigned value, or as a returned value. In each case it is a value written into a place where Java expects a value. None of these three placements, by itself, makes functions first-class in Java.
Mistakes Learners Make with Lambdas
Common mistake Concluding that Java has first-class functions because lambdas can be assigned to variables
What it looks likeA learner assigns x -> x * x to sqr and expects sqr(42) to work, the way it would in a language with first-class functions.
Why it failsAssigning a lambda to a variable does not make Java treat that variable as a callable function. The source says Java does not permit
sqr(42)for this variable.Do this insteadTreat the lambda as a value that needs a type. Ask what type the variable has before you ask whether it can be called.
Common mistake Reading the dummy parameter as a variable with a value
What it looks likeA learner tries to use x on its own, outside the lambda, expecting it to hold 42.
Why it failsThe dummy parameter is a placeholder naming the input the function will receive. It is not a standalone variable with a value.
Do this insteadRead the left side as the name of the input shape and the right side as the computation performed on that input.
Common mistake Ignoring the type when reasoning about the lambda
Why it failsJava is strongly typed, so the variable must be declared with a type. The type is what the functional interface supplies, and leaving it out leaves the question of what the name refers to unanswered.
Do this insteadWhen you read any lambda assignment, identify both the arrow expression and the declared type of the variable that holds it.
Common mistake Assuming that the arrow form alone is enough to make a lambda usable everywhere a function value would be
Practice Predicting the sqr Variable
What do you think happens?
A squaring lambda is assigned to a variable named sqr. Can you write sqr(42) and have Java compute 42 times 42?
Reveal answer
No, because sqr is a variable holding a lambda value, and Java does not allow it to be called like a function.
The source states that assigning a lambda to a variable does not make Java treat that variable as callable, so sqr(42) is not permitted. The reason is strong typing: the variable needs a type, and the functional interface supplies that type.
Take the lambda y -> y + y. Identify the dummy parameter, the arrow operator, and the computing expression. Then explain in one sentence why assigning it to a variable named doubler would still not let you write doubler(5) as a plain function call in Java.
Hints
- The dummy parameter is the placeholder on the left of the arrow.
- Connect your sentence to strong typing: what must the variable have before Java can accept it?
Key Takeaways
- A Java lambda expression is written with the arrow operator ->, with a dummy parameter on the left and the computing expression on the right.
- Assigning a lambda to a variable does not make Java treat that variable as callable, so a call such as
sqr(42)is not permitted. - Java is strongly typed, so a variable must be declared with a type; the functional interface supplies the type that fits a lambda value.
- A lambda can be passed as an argument, assigned to a variable, or returned, but none of these alone makes functions first-class in Java.