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.
|