Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A Java functional interface is an interface whose abstract methods amount to one logical method contract under the language rules. Lambdas and method references use that contract as their target type; the optional @FunctionalInterface annotation asks the compiler to verify that the interface qualifies. For common shapes, Java provides reusable types such as Function, Predicate, Consumer, and Supplier.

What makes an interface functional in Java?

The Java Language Specification (JLS) defines a functional interface by its abstract method contract, not by a simple count of declarations written in one source file. An interface qualifies when it has one functional abstract method, after accounting for inherited declarations and public instance methods matching methods of Object. See the Java SE 14 JLS, §9.8.

Inherited abstract methods can represent the same logical contract when their signatures are override-equivalent and their return types meet the specification’s compatibility rules. Consequently, several inherited declarations do not necessarily mean several distinct functional methods. Public Object methods such as toString do not add another contract, and default methods have implementations rather than adding abstract methods.

The JLS edition matters for release-specific rules. The cited Java SE 14 specification excludes sealed interfaces from being functional interfaces; check the JLS for the Java release you target before applying that detail to another release.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How lambdas and method references use functional interfaces

A lambda expression or method reference is not an untyped, standalone function value in Java. It is interpreted against a target type: a functional interface whose method parameters and result are compatible with the expression. The JDK documentation describes target typing in assignments, method invocations, and casts; see the Java SE 26 java.util.function package documentation.

@FunctionalInterface
interface Greeting {
    String greet(String name);
}

Greeting greeting = name -> "Hello, " + name;
System.out.println(greeting.greet("Mina"));

Here, Greeting supplies the target contract: it accepts a String and returns a String. A method reference can target an existing compatible method too:

Predicate<String> isEmpty = String::isEmpty;

Likewise, an API that expects a predicate gives a lambda its target type at the call site, as in stream.filter(e -> e.getSize() > 10).

What @FunctionalInterface does—and does not do

@FunctionalInterface is an optional annotation expressing design intent. The compiler reports a diagnostic if an annotated type does not meet the functional-interface requirements. But an interface that satisfies those requirements remains a valid lambda target even if the annotation is absent. Oracle’s Java SE 26 FunctionalInterface API documentation describes the annotation as informative and notes that instances can be created with lambda expressions, method references, or constructor references.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For a custom interface intended as a lambda target, adding the annotation is useful: it catches changes that accidentally disrupt the single logical method contract. It does not create that contract or make an otherwise ineligible interface functional.

Which built-in functional interface should you choose?

Start with the behavior’s shape: how many inputs it takes, and whether it returns a value, a boolean, or nothing. The java.util.function package supplies general-purpose types for common patterns.

Type Shape Typical role
Function<T,R> T -> R Transform an input into a result
Consumer<T> T -> void Perform an action using an input
Predicate<T> T -> boolean Test an input, such as a filter condition
Supplier<R> () -> R Produce a value without an input
BiFunction<T,U,R> (T,U) -> R Combine two inputs into a result
UnaryOperator<T> T -> T Transform a value while retaining its type
BinaryOperator<T> (T,T) -> T Combine two values of the same type

Names with an arity prefix, such as BiFunction, indicate additional inputs. The package also offers primitive-specialized variants for common shapes, which can avoid representing primitive values through boxed types. Consult the package documentation for the available interfaces and their contracts.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

When a custom functional interface is a better fit

A standard type is a good choice when its generic meaning is clear. A custom interface is preferable when a domain-specific name makes an API easier to understand, when callers need domain-specific documentation, or when the contract does not match a supplied shape. The JDK package documentation expressly leaves room for useful shapes it does not cover and for purpose-specific interfaces owned by the APIs that use them.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Meaning: Is this simply a transformation, test, action, or value source—or does the behavior represent a named business concept?
  • Inputs and result: Does a built-in type express the number of inputs and the return behavior accurately?
  • Type specialization: Would a primitive-specialized interface communicate the API more directly and avoid boxing?
  • API ownership: Does the library or package consuming the behavior already define an appropriate purpose-specific type?

Standard examples such as Runnable and Comparator also illustrate that functional interfaces are not limited to the java.util.function package. Choose a custom or existing domain interface for the clarity of its contract, not merely because it happens to have one method declaration.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.