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.
Runnable, ActionListener, and 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
}
}