Functional Interfaces in Java
Introduced in Java 8, Functional interfaces provide target types for Lambda Expressions and method references. Each functional interface has just one abstract (unimplemented) method. Basically, we would not be able to write lambda expressions without functional interfaces. So Functional interfaces actually bring lambda expressions to life.
A valid Functional interface in Java
public interface Flippable {
public void flip();
}
The Flippable interface above is a valid functional interface, because it has a single abstract (unimplemented) method. I'll show another example.
interface Rollable {
void roll();
default void print(String whatToPrint) {
System.out.println(whatToPrint);
}
default void printf(String whatToPrint) {
System.out.printf("%5s", whatToPrint);
}
static String display(String text) {
return "******" + text + "******";
}
}
The Rollable example above is also a valid Functional interface, though containing multiple default methods and a static method. Recall that default interface methods introduced in Java 8 are implemented (have a method body). Static methods are also implemented. There is only method in this interface which is unimplemented (abstract), this makes the interface a valid Functional interface.
Lambda Expressions
It is worth mentioning that Functional Interfaces provide the target types for Lambda expressions and method references. I will write on Lambda expressions in a different post. Since the purpose of Functional interfaces is to provide typing for lambda expressions, it makes sense for there to be exactly one unimplemented (abstract) method in a functional interface, and for its parameter and return types to match or adapt to that of the lambda expression.
Java's Built-in Functional Interfaces
Java contains a number of built-in functional interfaces that cover most use-cases. It makes sense to know them to avoid re-inventing the wheel. The location for these interfaces is the java.util.function package
Basic Functional Interfaces
- Function (unary function from T to R). It represents a function that takes a single parameter and returns a single value.
public interface Function <T,R > {
public R apply(T parameter);
}
- Consumer (unary function from T to void). Represents an operation that accepts a single input and returns no result. It operates by side-effects.
public interface Consumer<T> {
void accept (T t)
}
- Predicte (unary function from T to boolean). Represents a boolean-valued function of one-argument.
public interface Predicate<T> {
boolean test (T t)
}
- Supplier (nullary function to R). Returns a supplier of results
public interface Supplier<T> {
T get ()
}
We stop at this point to avoid information overload. Next, we will look at the primitive versions of Functional Interfaces, binary versions, UnaryOperator; we'd even develop code that use these functions. Might span up to 4 parts even. So subscribe to get my next post in your inbox.
Points to note about functional interfaces
- Any interface with a Single Abstract Method (SAM) is a functional interface
- Java's built-in functional interfaces are located in the java.util.function package
- A Functional interface can contain multiple default and/or methods alongside a single abstract method. Also note that Java 8 interface default methods are not abstract; making it possible to have a Functional interface with multiple default methods, even static methods but only one abstract method.
- A Functional interface does not necessarily need to be annotated with @FunctionalInterface. The annotation is present to aid lambda expression typing, so if you are to write a Functional interface, ensure to use the @FunctionalInterface annotation, because it will be used by lambda expressions, and the compiler can help you check before-hand.
Happy Learning!!!