🌐 First, What is a Functional Interface?
A functional interface is an interface with exactly one abstract method.
Examples:
✅ Runnable (1 method: run())
✅ Comparator (1 method: compare())
✅ Callable (1 method: call())
✅ Predicate (1 method: test())
@FunctionalInterface
public interface Printer {
void print(String message); // One abstract method = functional interface
}
🔥 Why Lambda Works Only with Functional Interfaces
Key Reason: Type Inference — Functional Interface gives context.
- A lambda itself has no type.
- To assign a lambda to a variable (or pass it into a method), the compiler needs to know what “shape” it fits — meaning:
- How many arguments?
- What are their types?
- What return type?
- Functional interfaces provide exactly that “shape” — because they have only one abstract method.
- That one abstract method defines the “functional shape” (called a functional descriptor) the lambda must match.
💡 Example
This works:
Consumer<String> printer = message -> System.out.println(message);
Why?
Consumeris a functional interface with:
void accept(T t)
The lambda message -> System.out.println(message) matches this perfectly:
- One argument (
String message) - Returns
void
This does NOT work:
interface NotFunctional {
void doSomething();
void doSomethingElse();
}
// ❌ This won't compile
NotFunctional obj = () -> System.out.println("Hello");
Why?
NotFunctionalhas two abstract methods, so Java can’t infer the shape of the lambda.- Java has no way to know if the lambda is meant to be
doSomething()ordoSomethingElse().
📣 Rule: Lambda Needs a Functional Descriptor
| Interface Type | Can Assign Lambda? | Why? |
|---|---|---|
| 1 abstract method (functional interface) | ✅ Yes | Compiler knows the “shape” |
| 2+ abstract methods (regular interface) | ❌ No | No way to know which method the lambda targets |
💡 How Java Knows the Types Inside the Lambda
Example:
BiFunction<String, Integer, String> repeat = (text, count) -> text.repeat(count);
BiFunctionis:
public interface BiFunction<T, U, R> {
R apply(T t, U u);
}
So:
T=StringU=IntegerR=String
✅ The lambda gets correct argument and return types from the functional interface.
🧰 Summary — Why Functional Interface is Required
| Why Functional Interface? | Explanation |
|---|---|
| Defines lambda’s shape | Number, type of parameters, and return type |
| Allows type inference | Compiler can validate lambda at compile time |
| Ensures compatibility | Lambdas work only in contexts expecting a single-method contract |
🔥 Pro Tip for Interviews
✅ If asked “Why only functional interfaces?”, say:
“Lambdas have no intrinsic type — they need a target type. Functional interfaces provide the functional descriptor that defines the lambda’s expected shape (parameters + return type). This makes type inference work and enables compile-time checks.”
✅ Mention:
- This is part of “Target Typing” in Java.
- Java avoids ambiguity by restricting lambdas to functional interfaces only.
🎯 Final Rule to Remember
“Lambda itself is just behavior. Functional interface provides the shape.”