Abstraction
Functional Interfaces
Master Single Abstract Method (SAM) contracts, @FunctionalInterface validation, and lambda integrations.
Interview: Highly tested: SAM rules, @FunctionalInterface compile checks, and integration with Java built-in function types.
A Functional Interface is an interface that declares exactly one abstract method (Single Abstract Method or SAM contract). They serve as the target types for lambda expressions, method references, and constructor references.
SAM Contract
Must contain exactly one abstract method. Can contain any number of default or static methods without violating functional requirements.
Validation
The optional @FunctionalInterface annotation instructs the compiler to verify that the interface meets the single abstract method constraint.
Standard Utilities
Java provides built-in functional interfaces (e.g. Predicate, Function, Consumer) in the java.util.function package.
Single Abstract Method (SAM) Specification
An interface is functional if it specifies exactly one abstract method. However:
- It can declare multiple
defaultorstaticmethods. These contain implementation bodies and do not count against the single abstract method limit. - If an interface declares an abstract method that overrides one of the public methods of
java.lang.Object(e.g.,@Override public boolean equals(Object obj);), it does not count toward the SAM limit, as every class inherits an implementation from Object.
Standard Java built-in Types
The java.util.function package provides standard functional interfaces to support lambda pipelines:
| Interface | Method Signature | Purpose |
|---|---|---|
Predicate<T> |
boolean test(T t) |
Evaluates an input against a condition, returning a boolean. |
Function<T, R> |
R apply(T t) |
Transforms an input of type T into an output of type R. |
Consumer<T> |
void accept(T t) |
Performs an action on an input, returning no result (void). |
Supplier<T> |
T get() |
Produces or supplies a value of type T, taking no arguments. |
Common Pitfalls
- Adding methods to Functional Interfaces: Adding a second abstract method to an interface annotated with
@FunctionalInterface, resulting in compilation failures. - Overusing Custom Functional Interfaces: Declaring new custom functional types instead of using standard built-in interfaces (like
BiFunctionorUnaryOperator), increasing API complexity.
Best Practices
- Always Annotate: Apply the
@FunctionalInterfaceannotation to make your design intent clear and prevent accidental method additions. - Reuse Built-In Functional Interfaces: Always look at the
java.util.functionpackage first before defining custom functional contracts.
Interview-Relevant Information
Q1: What is a Functional Interface? Can it have more than one method?
Answer: A functional interface is an interface with exactly one abstract method. It can have multiple static and default methods, as well as overridden Object class methods (like equals), without losing its functional status.
Q2: Why do we use the @FunctionalInterface annotation? Is it mandatory?
Answer: It is not mandatory; any interface with a single abstract method is functional by default. However, annotating it instructs the compiler to verify the single abstract method contract, preventing compile-time breaks if another developer adds abstract methods later.
Quick Checklist
Can you define a functional interface, explain which methods do not count against the SAM limit, and name four built-in functional interfaces and their signatures? If yes, you understand functional interfaces.
Use Cases
Defining target callbacks in stream pipelines (e.g. mapping, filtering, or reducing data elements).
Creating dynamic operation strategies (e.g. passing custom formatting calculations to log engines).
Common Mistakes
Declaring multiple abstract methods in functional interfaces, which disables lambda assignment.
Omitting the @FunctionalInterface annotation, leaving the interface vulnerable to accidental signature modifications.