What is Functional interface in Java 8
Well, a functional interface is nothing but an interface with just one abstract method e.g. Comparable, Runnable, EventListener, Comparator, etc. You can see these interfaces were present in Java even before JDK 8, but why do we call such interface functional interface?
you know that it allows you to pass the code like a function just like you pass data or object to the method.
These interface with just one abstract method was used to pass around code, just like you pass a function in functional programming language and that's why they are called functional interface.
For example,
you can directly pass the code to compare objects by creating an Anonymous class by implementing the Comparator interface as shown below:
Collections.sort(list,new Comparator(){
public int compare(String s1, String s2){
return s1.length() - s2.length();
}
});
So, if you look closely, you can see we are passing code to a function using these interfaces. They are also known as strategy interface because this is an implementation of Strategy pattern where the code which forms the Strategy is injected into the code which runs that strategy at runtime.
So, now that we know what is a functional interface, let's understand how they are related to a lambda expression, and how an understanding of functional interface is important for writing code using a lambda expression?
Well, the most important thing to remember is that the only use of lambda expression in Java is to convert them into a functional interface.
This means you can pass lambda expression if a method is accepting a functional interface, which further means, you can pass a lambda to all existing method which accepts Comparator, Runnable or any other interface which has got just one single abstract method
What does @Functional annotation do?
Now, let's see what does @Functional annotation do? Will it make an interface functional if you just put the @Functional annotation on top of that? Well, no, it doesn't do that. In fact, it's optional.
This means you can create a functional interface without using @Functioanl annotation just like you can override a method without putting the @Override annotation on top of a method. Then, what is the real purpose of @Functional annotation?
Well, it can ensure that the interface actually have just one abstract method and it also provides a hint to the tools like Javadoc that this interface is a functional interface. It's pretty much similar to @Override annotation, which helps to prevent human error by verifying that you actually overriding a method.
Similar to @Override its best practice to put the @Functional annotation on top of the method with single abstract methods to indicate to the tools like Javadoc that they are a functional interface.
All the new functional interface added in java.util.function package is annotated with the @Functional annotation.
Btw, Yes, we have got more functional interfaces in JDK 8, particularly general-purpose functional interfaces like Predicate, Supplier, Consumer, Function, BiFunction, UnaryOperator, etc.
These functional interfaces allow you to pass code to a function in form of lambda expression and enable the creation of powerful methods which can operate on those code like filter() method which accepts a Predicate and allows you to pass a code which accepts one argument and return boolean.
How Functional interface and Lamda Expression are related
How does knowledge of functional interface affect the writing of lambda expression? Well, unless you don't understand the functional interface, you can't write a lambda expression which can be converted into that functional interface.
For example, the merge() method of java.util.Map interface accepts a BiFunction, but if you don't know what is BiFunction then you cannot write lambda for that.
A BiFunction is a functional interface which has a method which accepts two arguments T and U and returns an object R.
This means you can pass a lambda to this method which works on two arguments and return an object like merge(key, value, (v1, v2) -> v1 + v2) here (v1, V2) -> v1 + v2 is a lambda expression which can be converted into an instance of BiFunction functional interface.
A rather simpler example is Predicate which accepts a type T and returns a boolean. If you look filter() method of Stream class it accepts a Predicate:
filter(Predicate predicate)
This means you can pass any lambda expression which accepts one argument and return boolean to this method e.g. age -> age > 15 or s -> s.length == 15, both are acceptable, but if you don't know what is a Predicate interface then you can't do that.
Another example of a functional interface is Consumer which accepts an argument of type T and return nothing. Good use of this is made in the forEach() method of Iterable in JDK 8, as shown below:
forEach(Consumer action)
You can see that forEach() accepts a Consumer, which means you can pass it a lambda expression which has one argument and returns nothing or the void e.g.
s -> System.out.println(s)
The code System.out.println() return nothing, it just prints line in the console.
You can see that if you know functional interface then you can easily write a lambda expression to pass around, hence good knowledge of functional interface is mandatory. I suggest you go through all functional interface in java.util.function package and understand them.
I'll explain some of the more complex functional interfaces from the java.util.function package in coming articles but if you can't wait then I suggest you go through this Java 9 Master Class course to learn more about lambdas and other Java 8 concepts.
That's all about what is a functional interface in Java. You have also learned what is the role of @Functional annotation and why a good knowledge of functional interface is required to make effective use of lambda expression in your code in Java 8.
Well, a functional interface is nothing but an interface with just one abstract method e.g. Comparable, Runnable, EventListener, Comparator, etc. You can see these interfaces were present in Java even before JDK 8, but why do we call such interface functional interface?
you know that it allows you to pass the code like a function just like you pass data or object to the method.
These interface with just one abstract method was used to pass around code, just like you pass a function in functional programming language and that's why they are called functional interface.
For example,
you can directly pass the code to compare objects by creating an Anonymous class by implementing the Comparator interface as shown below:
Collections.sort(list,new Comparator(){
public int compare(String s1, String s2){
return s1.length() - s2.length();
}
});
So, if you look closely, you can see we are passing code to a function using these interfaces. They are also known as strategy interface because this is an implementation of Strategy pattern where the code which forms the Strategy is injected into the code which runs that strategy at runtime.
So, now that we know what is a functional interface, let's understand how they are related to a lambda expression, and how an understanding of functional interface is important for writing code using a lambda expression?
Well, the most important thing to remember is that the only use of lambda expression in Java is to convert them into a functional interface.
This means you can pass lambda expression if a method is accepting a functional interface, which further means, you can pass a lambda to all existing method which accepts Comparator, Runnable or any other interface which has got just one single abstract method
What does @Functional annotation do?
Now, let's see what does @Functional annotation do? Will it make an interface functional if you just put the @Functional annotation on top of that? Well, no, it doesn't do that. In fact, it's optional.
This means you can create a functional interface without using @Functioanl annotation just like you can override a method without putting the @Override annotation on top of a method. Then, what is the real purpose of @Functional annotation?
Well, it can ensure that the interface actually have just one abstract method and it also provides a hint to the tools like Javadoc that this interface is a functional interface. It's pretty much similar to @Override annotation, which helps to prevent human error by verifying that you actually overriding a method.
Similar to @Override its best practice to put the @Functional annotation on top of the method with single abstract methods to indicate to the tools like Javadoc that they are a functional interface.
All the new functional interface added in java.util.function package is annotated with the @Functional annotation.
Btw, Yes, we have got more functional interfaces in JDK 8, particularly general-purpose functional interfaces like Predicate, Supplier, Consumer, Function, BiFunction, UnaryOperator, etc.
These functional interfaces allow you to pass code to a function in form of lambda expression and enable the creation of powerful methods which can operate on those code like filter() method which accepts a Predicate and allows you to pass a code which accepts one argument and return boolean.
How Functional interface and Lamda Expression are related
How does knowledge of functional interface affect the writing of lambda expression? Well, unless you don't understand the functional interface, you can't write a lambda expression which can be converted into that functional interface.
For example, the merge() method of java.util.Map interface accepts a BiFunction, but if you don't know what is BiFunction then you cannot write lambda for that.
A BiFunction is a functional interface which has a method which accepts two arguments T and U and returns an object R.
This means you can pass a lambda to this method which works on two arguments and return an object like merge(key, value, (v1, v2) -> v1 + v2) here (v1, V2) -> v1 + v2 is a lambda expression which can be converted into an instance of BiFunction functional interface.
A rather simpler example is Predicate which accepts a type T and returns a boolean. If you look filter() method of Stream class it accepts a Predicate:
filter(Predicate predicate)
This means you can pass any lambda expression which accepts one argument and return boolean to this method e.g. age -> age > 15 or s -> s.length == 15, both are acceptable, but if you don't know what is a Predicate interface then you can't do that.
Another example of a functional interface is Consumer which accepts an argument of type T and return nothing. Good use of this is made in the forEach() method of Iterable in JDK 8, as shown below:
forEach(Consumer action)
You can see that forEach() accepts a Consumer, which means you can pass it a lambda expression which has one argument and returns nothing or the void e.g.
s -> System.out.println(s)
The code System.out.println() return nothing, it just prints line in the console.
You can see that if you know functional interface then you can easily write a lambda expression to pass around, hence good knowledge of functional interface is mandatory. I suggest you go through all functional interface in java.util.function package and understand them.
I'll explain some of the more complex functional interfaces from the java.util.function package in coming articles but if you can't wait then I suggest you go through this Java 9 Master Class course to learn more about lambdas and other Java 8 concepts.
That's all about what is a functional interface in Java. You have also learned what is the role of @Functional annotation and why a good knowledge of functional interface is required to make effective use of lambda expression in your code in Java 8.
No comments:
Post a Comment