Course Content
Core Java
About Lesson

A functional interface in Java is an interface that contains exactly one abstract method. They can have only one functionality to exhibit. From Java 8 onwards, lambda expression can be used to represent the instance of a functional interface. A functional interface can have any number of default methods.

RunnableActionListenerand Comparable are some of the examples of functional interfaces.

Characteristics

Single Abstract Method: A functional interface contains exactly one abstract method

Default and Static Methods: Can contain any number of default and static methods

@FunctionalInterface Annotation: Optional annotation to indicate an interface is intended to be a functional interface, providing compile-time checking. This annotation helps to ensure that your interface remains functional by allowing the compiler to generate an error if the interface violates the contract of a functional interface.

Syntax

@FunctionalInterface
public interface MyFunctionalInterface {
    void execute();
}

Any interface with a SAM(Single Abstract Method) is a functional interface, and its implementation may be treated as lambda expressions.

Built-in Functional Interfaces

Predicate<T>

Represents a boolean-valued function of one argument. It has method- boolean test(Test t)

import java.util.function.Predicate;

public class PredicateExample {
    public static void main(String[] args) {
        // Using an anonymous class to implement Predicate
        Predicate<String> isEmpty = new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.isEmpty();
            }
        };

        System.out.println(isEmpty.test(""));     // Output: true
        System.out.println(isEmpty.test("hello")); // Output: false
    }
}

Function<T, R>

Represents a function that accepts one argument and produces a result. It has method- R apply(T t)

import java.util.function.Function;

public class FunctionExample {
    public static void main(String[] args) {
        // Using an anonymous class to implement Function
        Function<String, Integer> lengthFunction = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return s.length();
            }
        };

        System.out.println(lengthFunction.apply("hello")); // Output: 5
    }
}

Supplier<T>

Represents a supplier of results. It has method: T get()

import java.util.function.Supplier;

public class SupplierExample {
    public static void main(String[] args) {
        // Using an anonymous class to implement Supplier
        Supplier<String> supplier = new Supplier<String>() {
            @Override
            public String get() {
                return "Hello, Supplier!";
            }
        };

        System.out.println(supplier.get()); // Output: Hello, Supplier!
    }
}

Consumer<T>

Represents an operation that accepts a single input argument and returns no result. It has method: void accept(T t)

import java.util.function.Consumer;

public class ConsumerExample {
    public static void main(String[] args) {
        // Using an anonymous class to implement Consumer
        Consumer<String> printer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };

        printer.accept("Hello, Consumer!"); // Output: Hello, Consumer!
    }
}

BiFunction<T, U, R>

Represents a function that accepts two arguments and produces a result. It has method: R apply(T t, U u)

import java.util.function.BiFunction;

public class BiFunctionExample {
    public static void main(String[] args) {
        // Using an anonymous class to implement BiFunction
        BiFunction<Integer, Integer, Integer> add = new BiFunction<Integer, Integer, Integer>() {
            @Override
            public Integer apply(Integer a, Integer b) {
                return a + b;
            }
        };

        System.out.println(add.apply(2, 3)); // Output: 5
    }
}

Custom Functional Interface

Following is the code to create own functional interfaces

@FunctionalInterface
interface CustomFunctionalInterface {
    String reverse(String s);
}

public class CustomFunctionalInterfaceExample {
    public static void main(String[] args) {
        // Using an anonymous class to implement the reverse method
        CustomFunctionalInterface reverser = new CustomFunctionalInterface() {
            @Override
            public String reverse(String s) {
                return new StringBuilder(s).reverse().toString();
            }
        };
        
        // Invoking the method
        System.out.println(reverser.reverse("hello")); // Output: olleh
    }
}

Scroll to Top