Functional interface in Java-8
Functional interface by definition is an interface which contains only one single method. The compiler ensures this check with @FunctionalInterface annotation.
Basically, with this you can define the inline implementation of the interface via lambda expression
Let’s code now-
First, we will define a functional interface-
package com.example.functionalinterface;
@FunctionalInterface
public interface Operation
{
int square(int value);
}
Now, let’s use this method-
package com.example.functionalinterface;public class OperationClient
{
public static void main(String[] args)
{
Operation operation = (value) -> value*value;
System.out.println(operation.square(5));
}
}
Here, we are defining an inline implementation of the square method with lambda expression and when we call the method with operation.square(5) it prints out 25.
What are we saving with this?
Firstly, we don’t need to first define a concrete implementation class put the code there then in main OperationClient class point operation to the implementation instance and use it. So, basically a lot of code gets saved.
Now, the question comes is if the functional interface is only going to have a single method, with no concrete implementation then why can’t we make it generic and use it anywhere.
Yes, and for that Java has provided the Function, which has a pretty simple definition-
Now, if I run the same example with Function-
package com.example.functionalinterface;
import java.util.function.Function;
public class OperationClient
{
public static void main(String[] args)
{
Function<Integer, Integer> operation = (value) -> value*value ;
System.out.println(operation.apply(5));
}
}
Now, Im saving the time to create the FunctionalInterface aswell-
Can I pass this definition as an argument to a method?
Well, yes and it gives more flexibility to pass on the implementation-
package com.example.functionalinterface;
import java.util.function.Function;
public class OperationClient
{
public static void main(String[] args) {
new OperationClient().compute( (value) -> value*value, 5);
}
public void compute(Function<Integer, Integer> operation, int param)
{
System.out.println(operation.apply(param));
}
}
Now, if I use this with the combination of default method, then the combination becomes extremely good-
Ex: the compose() and andThen() methods of Function interface. This helps in the orchestration of your business logic implementation
default <V> Function<V, R> compose(Function<? super V, ? extends T> before)
{
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
This is like the pre-apply method for your functional interface definition. It simply checks if the before is defined and if before is defined then that is called first, which by itself returns the real apply implementation and then the real apply() method is called. Same goes with andThen() implementation-
Do I need @FunctionalInterface anymore if Function is already there?
Yes, there will be use-cases where you want your custom methods always present in the interface with the help of default methods and only for dynamic implementations you are relying on functional interface method-
Can I use static methods alongside the abstract method?
The definition of Functional interface is that there should only be a single abstract methods , so we can have multiple default and static methods in the FunctionalInterface-
@FunctionalInterface
public interface Operation
{
int square(int value);
static String getOperationNature()
{
return "This is operation interface";
}
}
In summary, FunctionalInterface do make code look cleaner and avoid making a lot of concrete classes. You can attach behaviour to an interface dynamically, without having to go through the tedious process of creating classes and all-