Lambdas & Method References
The Problem Lambdas Solve
When an interface declares exactly one abstract method (a functional interface), implementing it with a full named class — or even an anonymous class — is a lot of ceremony for something conceptually simple: "here's the one bit of behavior you asked for." A lambda expression lets you write that one method's body directly, with no class declaration at all:
public interface DoubleSupplier
{
double getAsDouble(); // exactly one abstract method — this is a functional interface
}
// Without a lambda: a full anonymous class just to supply one value
DoubleSupplier speed = new DoubleSupplier()
{
@Override
public double getAsDouble() { return joystick.getY(); }
};
// With a lambda: the same thing, far more directly
DoubleSupplier speed = () -> joystick.getY();
WPILib commands and suppliers are built almost entirely on this pattern — this is exactly what makes lambdas so central to command-based programming (Ch.25).
Lambda Syntax
A lambda expression has three parts: a parameter list in parentheses, the arrow ->, and a body:
(parameters) -> expression
- Parameter types are inferred, not written — the compiler already knows them from the functional interface being implemented.
- Parentheses can be dropped around a single parameter:
p -> p.getY()is valid, just like(p) -> p.getY(). - A single expression is the return value automatically — no
returnkeyword needed. A multi-statement body needs braces and an explicitreturn:
DoubleSupplier speed = () -> joystick.getY(); // single expression — auto-returned
DoubleSupplier clampedSpeed = () -> { // multi-statement body needs braces + return
double raw = joystick.getY();
return Math.max(-1.0, Math.min(1.0, raw));
};
A lambda with more than one parameter lists them comma-separated inside the parentheses:
public interface IntBinaryOperation
{
int apply(int a, int b);
}
IntBinaryOperation add = (a, b) -> a + b;
Common Functional Interfaces You'll Actually Use
Java (and WPILib) ship several ready-made functional interfaces, so you rarely need to declare your own:
Runnable stopAll = () -> intake.stop(); // no arguments, no return value
DoubleSupplier speed = () -> joystick.getY(); // no arguments, returns a double
BooleanSupplier hasGamePiece = () -> intake.hasPiece(); // no arguments, returns a boolean
Method References: An Even Shorter Form
When a lambda's entire body is just calling one existing method, a method reference (::) says the same thing even more directly:
Runnable stopAll = () -> intake.stop(); // a lambda...
Runnable stopAll2 = intake::stop; // ...is exactly equivalent to this method reference
intake::stop reads as "the stop method, called on intake" — Java fills in the call automatically, with whatever arguments the functional interface's method expects. Method references exist purely as a shorthand for a lambda that does nothing but forward to an existing method — anywhere a method reference works, the equivalent lambda would work identically.
Common Pitfalls
- Writing parameter types into a lambda.
(Person p) -> p.getAge()— while technically legal — is unusual style; letting the compiler infer the type (p -> p.getAge()) is the normal convention, since the functional interface already pins down what typephas to be. - Forgetting
returnin a multi-statement lambda body. A single-expression lambda auto-returns its value, but a{ }block body needs an explicitreturn, exactly like a regular method. - Reaching for a method reference when the lambda does more than forward one call.
() -> { intake.stop(); logEvent("stopped"); }genuinely needs a lambda — a method reference only replaces a lambda that does nothing but call one existing method.
Key Takeaways
- A lambda expression is a compact way to implement a functional interface (an interface with exactly one abstract method) inline, without writing a class.
- Syntax:
(parameters) -> expression(or{ statements; return value; }for a multi-statement body); parameter types are inferred, and parentheses can be dropped for a single parameter. Runnable,DoubleSupplier, andBooleanSupplierare common ready-made functional interfaces WPILib code uses constantly.- A method reference (
object::method) is exact shorthand for a lambda that does nothing but call one existing method.
Derived from other-reference-repo: oracle-java-tutorials/lambdas/lambda-expressions.md (ORACLE 12.2)
Deck context: mechacoder-test/src/lessons/java-1.js, slide 12 ("Lambdas & Method References")