Sitemap
Guhan B

Guhan B

Hello Internet 🖖, I am a Software developer with a strong focus on building robust 🚀 and scalable 📈 applications .

Java : Functional Interface

4 min readMay 19, 2025

--

Press enter or click to view image in full size

In this article, We will explore the fundamental concepts around Functional Interfaces, understand their purpose, characteristics, and how they relate to Lambda Functions and Method References. We will also explore various built-in functional interfaces provided by Java in the package java.util.function and learn how to create custom functional interfaces through practical examples.

What are Functional Interface?

A Functional Interface is an Java interface that contains only a Single Abstract Method (Hence, also known as SAM Interface). Since functional interfaces have only one abstract method they server as the target type for lambda functions and method references.

Functional interfaces can have multiple default and static methods, But they must strictly have only one abstract method.

To indicate that an interface is intended to be a functional interface, we use the @FunctionalInterfaceannotation. Using the annotation is optional, but it is a good practice as it helps the developers and IDE to understand the intended use of the interface.

When an interface is marked with @FunctionalInterface annotation and it has more than one abstract method, the compiler flags an “Unexpected @FunctionalInterface annotation” error.

Build-In Functional Interface

Java provides a set of built-in functional interfaces under the package java.util.function to cover various use cases. They can be categorized into four core types. Consumer, Supplier, Predicate and Function.

1. Consumer

The Consumer functional interface represents an operation that takes a single input of type T and does not return any value.

@FunctionalInterface
interface Consumer<T> {
void accept(T value);
}

The following example shows the usage of Consumer interface, for printing the elements of a List.

import java.util.List;
import java.util.function.Consumer;

public Example {
public static void main(String[] args) {
List<String> names = List.of("Tony", "Peter", "Bruce");

Consumer<String> print = name -> System.out.println(name);

names.forEach(print);
}
}

2. Supplier

The Supplier functional interface represents an operation that does not take any input and returns a value of type T.

@FunctionalInterface
interface Supplier<T> {
T get();
}

The following example shows the usage of Supplier interface, for generating random number.

import java.util.function.Supplier;

public Example {
public static void main(String[] args) {
Supplier<Double> randomNumberGenerator = () -> Math.random();

System.out.println(randomNumberGenerator.get());
}
}

3. Predicate

The Predicate functional interface represents an operation that takes a single input of type T and returns a boolean value.

@FunctionalInterface
interface Predicate<T> {
boolean test(T value);
}

The following example shows the usage of Predicate interface, to extract even numbers from a List.

import java.util.function.Predicate;

public Example {
public static void main(String[] args) {
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

Predicate<Integer> check = i -> i % 2 == 0;

List<Integer> evenNumbers = numbers.stream()
.filter(check)
.collect(Collectors.toList());
}
}

Get Guhan B’s stories in your inbox

Join Medium for free to get updates from this writer.

4. Function

The Function functional interface represents an operation that takes a single input of type T and returns a value of type R.

@FunctionalInterface
interface Function<T, R> {
R apply(T value);
}

The following example shows the usage of Function interface, to square the numbers on a List.

import java.util.function.Function;

public Example {
public static void main(String[] args) {
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

Function<Integer, Integer> square = i -> i * i;

List<Integer> squaredNumbers = numbers.stream()
.map(square)
.collect(Collectors.toList());
}
}

Variants of Consumer, Supplier, Predicate & Function

Apart from the four core functional interfaces describe above, Java also provides multiple specialized variants of these four core built-in interfaces based on the number or type of input and type of output. The exhaustive list of all the functional interfaces provided by Java can be found in the official Java API documentation here.

Primitive based functional interfaces like IntConsumer, IntSupplier, IntPredicate, IntFunction etc. are provided to avoid the overhead of autoboxing and unboxing while using wrapper classes.

Custom Functional Interface

The built-in functional interfaces provided by Java will be useful for a wide range of scenarios, but you may encounter scenarios where none of the built-in functional interfaces meets your requirements. In such cases, you can create your own custom function interfaces.

  1. Define a Java interface that has a single abstract method.
  2. Optionally mark it with the @FunctionalInterface annotation.
@FunctionalInterface
interface CustomFunctionalInterface<T> {
void action(T value);
}

Now the CustomFunctionalInterface can be used with a suitable lambda function or a method reference.

Functional Interfaces and Method References

Method Reference is a feature in Java using which normal methods can be passed instead of lambda functions to functional interfaces. Consider the example of Consumer functional interface, where we create a lambda method which calls System.out.println. Using method reference we can directly pass the System.out.println.

import java.util.List;
import java.util.function.Consumer;

public Example {
public static void main(String[] args) {
List<String> names = List.of("Tony", "Peter", "Bruce");

names.forEach(System.out::println);
}
}

Method reference uses the :: operator to separate the object / class from the method. There are four variants of method references

  1. Reference to Static Methods
    class::staticMethod
  2. Reference to Instance Method (Using instance)
    object::instanceMethod
  3. Reference to Instance Method (Using class)
    class::instanceMethod
  4. Reference to Constructor Method
    class::new or class[]::new

Method references can also be use with this and super keywords.

Conclusion

In this article, we explored Functional Interfaces in Java — interfaces with a single abstract method that serve as the foundation for lambda functions and method references. We examined their characteristics, the role of the @FunctionalInterface annotation, and how they enable functional programming in Java. We also walked through the core built-in interfaces like Consumer, Supplier, Predicate, and Function, along with practical examples and Method References. As the backbone of lambda functions, understanding functional interfaces is essential for unlocking the full potential of modern Java.

--

--