Hurry! Try our new Interactive Courses for FREE. 🥳   🚀

Java 8 Functional Interface

A functional interface is a concept that was introduced in Java 8. An interface that has the only a single abstract method and marked with @FunctionalInterface annotation is called functional interface.

The functional interface is used to support the functional programming approach, lambda expression, and method reference as well.

A functional interface is also known as SAM interface because of the Single Abstract Method (SAM).

Let's see how to create a functional interface, although Java provides various built-in functional interfaces that we have summarized in the table at the end of the topic.

Example: Functional Interface

We are creating a functional interface that is marked with annotation and contains only a single abstract method.

@FunctionalInterface
interface Printable{
        public void print();
}

Example: Wrong Functional Interface

If we use functional interface annotation with an interface that has more than one abstract methods then the compiler will generate an error.

@FunctionalInterface
interface Printable{
        public void print();
        public void print3D();
}


Error:
Invalid '@FunctionalInterface' annotation; Printable is not a functional interface

Functional Interface With Non-Abstract Methods

A functional interface can have default and static methods also like normal interface but only one abstract method. Below is a valid functional interface.

@FunctionalInterface
interface Printable{

	// Abstract method
	public void print();

	// non-abstract (static) method
	public static void print3D() {
		System.out.println("3D Printing");
	}
}

How to implement a functional interface?

A functional interface can be implemented either by using lambda expression or method reference. To understand lambda expression you can visit our <a href=”lambda-expression”>Lambda Expression</a> topic.

Let's see some examples to implement a functional interface.

Example: Functional Interface

In this example, we are implementing a functional interface using a lambda expression. An abstract method print() is implemented inside the Demo class using the lambda expression.

@FunctionalInterface
interface Printable{
	public void print();
	public static void print3D() {
		System.out.println("3D Printing");
	}
}

public class Demo {
	public static void main(String[] args) {
		// Implementing functional interface using lambda
		Printable p = ()->System.out.println("Printing...");
		p.print();
	}
}


Printing...

Example: Functional Interface using Method Reference

In this example, we are implementing a functional interface using method reference. Method reference is a concept in which we can refer a method to an abstract method of an interface. See the below example.

@FunctionalInterface
interface Printable{
	public void print();
	public static void print3D() {
		System.out.println("3D Printing");
	}
}


public class Demo {
	public static void main(String[] args) {
		Demo demo = new Demo();
		// Referring to a non-functional method
		Printable p = demo::printColor;
		// calling abstract method
		p.print();
	}

	// Implementation of print() abstract method
	public void printColor() {
		System.out.println("Color Printing...");
	}
}


Color Printing...

Valid: Extending Interface

A functional interface can extend only a non-functional interface that does not have any abstract method.

interface Drawable{
	public default void draw() {
		System.out.println("Draw Image");
	}
}


@FunctionalInterface
interface Printable extends Drawable{
	public void print();
	public static void print3D() {
		System.out.println("3D Printing");
	}
}

Not Valid: Extending Interface

A functional interface can not extend any interface that has one or more abstract methods. The compiler will report an error at compile time.

interface Drawable{
	public void draw();
}


@FunctionalInterface
interface Printable extends Drawable{
	public void print();
	public static void print3D() {
		System.out.println("3D Printing");
	}
}

Error: Invalid '@FunctionalInterface' annotation; Printable is not a functional interface

Java Built-in Functional Interface

Java provides various built-in functional interfaces to supports functional programming although we can create our own functional interface as we did start of the topic.

The following table contains the list of functional interfaces that are located into java.util.function package.

Interface

Description

BiConsumer<T,U>

It represents an operation that accepts two input arguments and returns no result.

Consumer<T>

It represents an operation that accepts a single argument and returns no result.

Function<T,R>

It represents a function that accepts one argument and returns a result.

Predicate<T>

It represents a predicate (boolean-valued function) of one argument.

BiFunction<T,U,R>

It represents a function that accepts two arguments and returns a a result.

BinaryOperator<T>

It represents an operation upon two operands of the same data type. It returns a result of the same type as the operands.

BiPredicate<T,U>

It represents a predicate (boolean-valued function) of two arguments.

BooleanSupplier

It represents a supplier of boolean-valued results.

DoubleBinaryOperator

It represents an operation upon two double type operands and returns a double type value.

DoubleConsumer

It represents an operation that accepts a single double type argument and returns no result.

DoubleFunction<R>

It represents a function that accepts a double type argument and produces a result.

DoublePredicate

It represents a predicate (boolean-valued function) of one double type argument.

DoubleSupplier

It represents a supplier of double type results.

DoubleToIntFunction

It represents a function that accepts a double type argument and produces an int type result.

IntToDoubleFunction

It represents a function that accepts an integer argument and returns a double.

IntToLongFunction

It represents a function that accepts an integer argument and returns a long.

IntUnaryOperator

It represents an operation on a single integer operand that produces an integer result.

LongBinaryOperator

It represents an operation upon two long type operands and returns a long type result.

LongConsumer

It represents an operation that accepts a single long type argument and returns no result.

LongFunction<R>

It represents a function that accepts a long type argument and returns a result.

LongPredicate

It represents a predicate (boolean-valued function) of one long type argument.

LongSupplier

It represents a supplier of long type results.

LongToDoubleFunction

It represents a function that accepts a long type argument and returns a result of double type.

LongToIntFunction

It represents a function that accepts a long type argument and returns an integer result.

LongUnaryOperator

It represents an operation on a single long type operand that returns a long type result.

ObjDoubleConsumer<T>

It represents an operation that accepts an object and a double argument, and returns no result.

ObjIntConsumer<T>

It represents an operation that accepts an object and an integer argument. It does not return result.

ObjLongConsumer<T>

It represents an operation that accepts an object and a long argument, it returns no result.

Supplier<T>

It represents a supplier of results.

ToDoubleBiFunction<T,U>

It represents a function that accepts two arguments and produces a double type result.

ToDoubleFunction<T>

It represents a function that returns a double type result.

ToIntBiFunction<T,U>

It represents a function that accepts two arguments and returns an integer.

ToIntFunction<T>

It represents a function that returns an integer.

ToLongBiFunction<T,U>

It represents a function that accepts two arguments and returns a result of long type.

ToLongFunction<T>

It represents a function that returns a result of long type.

UnaryOperator<T>

It represents an operation on a single operand that returnsa a result of the same type as its operand.