What are functional interfaces in Java?
A functional interface in Java is an interface that declares exactly one abstract method. This single-abstract-method (SAM) constraint makes the interface usable as the target type for a lambda expression or method reference, enabling functional-style programming introduced in Java 8.
The @FunctionalInterface annotation is optional but strongly recommended. It instructs the compiler to enforce the SAM constraint and signals intent to readers. If you accidentally add a second abstract method, the compiler emits an error rather than silently breaking all lambda assignments.
The java.util.function package ships with a rich set of built-in functional interfaces covering the most common patterns. Predicate<T> takes a T and returns boolean (testing/filtering). Function<T, R> maps T to R (transformation). Consumer<T> takes a T and returns void (side effects). Supplier<T> takes nothing and returns T (factories/lazy evaluation). BinaryOperator<T> takes two T arguments and returns T (reduction). Primitive specializations like IntPredicate and LongSupplier avoid autoboxing overhead.
Functional interfaces can have any number of default and static methods — only abstract methods count toward the SAM constraint. For example, Predicate<T> has default methods and(), or(), and negate() that compose predicates.
Before Java 8, single-method interfaces like Runnable and Comparator were already widely used in anonymous inner classes. Lambda expressions are essentially a syntactic shorthand for anonymous implementations of functional interfaces — the compiler infers the target type from context.
A key design implication: when writing an API that accepts behavior as a parameter (callbacks, strategies, transformations), prefer accepting a standard functional interface from java.util.function rather than defining a custom one. This integrates naturally with the streams API and keeps the method signature immediately recognizable to Java developers.
Correctly defines the SAM constraint, mentions @FunctionalInterface annotation, and names at least two built-in examples from java.util.function.
Adds that default/static methods don't count toward SAM, connects functional interfaces to lambda target types, names Predicate/Function/Consumer/Supplier with their signatures, and mentions pre-Java 8 examples like Runnable.
Reading the answer is step one. Explaining it unprompted — under interview pressure — is what actually matters. Get AI-graded feedback on your answer with follow-up probes on your weak points.
Get Graded — Free Assessment