Diving Deep in Lambda Expressions: Part 2
Posted By : Raj Wadhwa | 19-Nov-2017
This blog post is the second in the series of Diving Deep into the Lambda Expressions. Here we will discuss about Funtional Interfaces.By now, you already know what a Funtional Interface is. However, let’s dive deep into it.
A functional interface, you already know, has one abstract method. It can be a target for a Lambda Expression or Method Reference. The use of the word abstract is significant. Prior to Java 8, all the methods in interfaces were considered abstract by default – there wasn’t any need to mention it.
@FunctionalInterface
public interface PalindromeChecker {
boolean isPalindrome(String s);
}
You can leave the access modifier as well as the abstract keyword. Generally, to denote the functional interfaces, we use @FuntionalInterface annotation. Java 8 provides this annotation in the java.lang package that can be applied to the interfaces as shown above.
Annotation is not mandatory, however it serves two purposes
- It generates an error when more than 1 abstract method declarations are present.
- Another benefit is that it helps in generating a statement to notify that interface is functional in Javadocs.
Functional Interface can have:
- Only one abstract method (as described above)
- default method with proper implementation
- a static method with implementation
as shown below :
public interface MyInterface {
int myMethod();
// int mySecondMethod();
default String sayHello() {
return "Hello World";
}
static void myStaticMethod() {
System.out.println("Printing from a static method");
}
}
If we uncomment the line in the above method for my second method, with this annotation, it will throw an error saying that “multiple non-overriding abstract methods found”.If another interface extends this interface, and include another abstract method, that new interface can’t be used as a target for functional interfaces Lambda Expressions or method references.
Below interface will be a valid one but it’s not a functional interface.
public interface MyChildInterface extends MyInterface{
int another();
}
Below declaration will give the compilation error because of the @FunctionalInterface annotation:
@FunctionalInterface
public interface MyChildInterface extends MyInterface{
int another();
}
Please note that below declaration won’t give any error:
@FunctionalInterface
public interface MyChildInterface extends MyInterface{
boolean equals(Object o);
}
This means we can declare methods in Object as abstract in an interface, but that doesn’t make them abstract. Usually, the reason for doing it so to add documentation that explains the contract of the interface. Rules for functional interfaces say that method from Object doesn't count against the single method limit, so our above interface, MyChildInterface is still a
Same goes for the Comparator interface in java.util, as shown below :
Default Methods in interfaces
The traditional reason why java never supported multiple inheritances is the so-called diamond problem. Java’s approach was to prohibit multiple
- boolean isEmpty()
- int size()
isEmpty() method can be implemented in terms of size also.
Since Collection is an interface, you can’t do this in an interface itself. Instead, the standard library includes an abstract class, AbstractCollection, which includes, among other code, exactly the implementation of isEmpty. Two scenarios are possible here:
- If you don’t have a Super Class and you want to create your own implementation class, you can extend AbstractCollection and you get the isEmpty method for free.
- If you already have a Super Class, you have to implement the Collection interface instead and remember to provide your own implementations of isEmpty as well as size.
Now, this imposes some restrictions on developers to be bounded by the rules.
To avoid this, Java 8 introduced the ability to add default implementations to the interface methods. All that you have to do is to add a “default” keyword and provide an implementation.
@FunctionalInterface
public interface MyChildInterface extends MyInterface{
boolean equals(Object o);
}
default void printThis(String s) {
System.out.println(s);
}
}
Many of the existing interfaces in Java have been enhanced with default methods to introduce the backward compatibility. Normally, when a new method is introduced in the interfaces, all the existing implementation will have to be modified to add the implementation of newly added methods. However, with this addition of default methods functionality, it is possible. No need to change the existing implementations. :)
java.util.Collection now contains the following default methods:
- default boolean removeIf(Predicate<? Super E> filter)
- default Stream<E> stream()
- default Stream<E> parallelStream()
- default Spliterator<E> spliterator
Note: If a class implements more than one interface with the same default method declarations (with same or different implementations), Our class will have to implement the method in the class itself.
Static Methods
To create the static method in interfaces, add static keyword ahead of the method declaration and provide the default implementation.To access it, classes don't need to implement an interface to use its static method. One example of such a method (static) is the comparing() method in the java.util.Comparator interface, along with its primitive variants:
- comparing
- comparing long
- comparingDouble
Comparator interface also has static methods
You can always check the Java Doc for more info on various Functional Interfaces. In the next blog, we will explore java.util.function package for all the functional interfaces that are provided by JDK for general purposes.
Cookies are important to the proper functioning of a site. To improve your experience, we use cookies to remember log-in details and provide secure log-in, collect statistics to optimize site functionality, and deliver content tailored to your interests. Click Agree and Proceed to accept cookies and go directly to the site or click on View Cookie Settings to see detailed descriptions of the types of cookies and choose whether to accept certain cookies while on the site.
About Author
Raj Wadhwa
Raj is a Sr. Project Manager with experience of almost 7 Years. He is an avid Reader, Programmer, Loves playing Football, and a Foodie.