This post works as an introduction to the Functional Interfaces in Java 8. We will cover some basics of the Functional Interfaces introduced in Java 8.
Functional Interfaces in Java 8
Java has always been called as OOP (Object Oriented Programming)
language. Functions do not exist independently in Java and everything is part of Class and use to class/object to invoke any function (ie, JNI). Functional Programming Language is written for independent functions and uses them when required, such as C++, JavaScript.
They introduced function Interface in Java8 as new features along with Stream API, Time API, Lambda Expression, etc., Function Interface having only one abstract method and can have multiple default methods. To put it differently, an interface with only abstract method is called a functional interface. We also call these interfaces as Single Abstract Method interfaces (SAM Interfaces). We have the following options when working with functional interfaces in Java.
- Use the pre-defined functional interfaces available with JDK.
- Create your own functional interface if OOTB interfaces are not meeting your requirements.
We can use lambda expressions in Java in the context of functional interface, i.e. you need to use either available functional interfaces or create your own to use the lambda expressions in Java. To check your understanding, let’s look at the following examples and identify which of these are a functional interface:
public interface example1 {
int test();
}
public interface example2 extends example1 {
int test2();
}
public interface example3 {
int test3();
int test4();
}
1. Creating Custom Functional Interface Example
@FunctionalInterface
annotation was introduced along with other annotation in Java 8, which can validate at the compile time. Keep in mind that it’s an optional annotation. This annotation only indicates that the interface is intended as a functional interface.
Let’s create a simple example to understand few details of the @FunctionalInterface.
@FunctionalInterface
public interface Account {
int returns();
default void printDetails() {
System.out.println("Default Methods");
}
}
An interface declares an abstract method overriding one of the public methods of java.lang.Object
, that also does not count toward the interface’s abstract method count since any implementation of the interface will have an implementation from java.lang.Object
or elsewhere (i.e., abstract methods that override the method in the object).
@FunctionalInterface
public interface Account {
int returns();
default void printDetails() {
System.out.println("Default Methods");
}
/*
* Overridden from Object class
*/
public String toString();
public int hashCode();
}
FunctionalInterface
annotation is not mandatory to use because of the compiler will treat any interface meeting the definition of a functional interface as a functional interface whether a FunctionalInterface
annotation is present on the interface declaration. Java earlier version having a single abstract method in the interface and they were known as simple abstract method interface e.g.,Runnable Interface (Run method), Comparator Interface.
2. Predefined Functional Interface Example
You can always use the available functional interfaces if they are fulfilling your need. To give you an overview of how to use the OOTB functional interfaces in Java, let’s see how the Predicate<T> will work. Here is the definition for this functional interface:
@FunctionalInterface
public interface Predicate < T > {
boolean test(T t);
//other methods
}
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class FunctionalInterfaceExample {
public static void main(String[] args) {
List < Integer > input = Arrays.asList(45, 1, 34, 56, 33, 18);
Predicate < Integer > check = n - > n > 18; // predicate to filter number greater than 18
input.stream()
.filter(check).forEach(System.out::println); //45,34,56,33
}
}
3. Functional Interfaces – Important points
Here are some important points which will help us understand it clearly
- The
@FunctionalInterface
annotation is optional. An interface is a valid interface if it only contains one abstract method. - The
@FunctionalInterface
annotation can help in compile time validation. - Functional interface in method can have only one abstract method and default methods have an implementation, we can add default methods in the functional interface ( check example 1 in this article).
- If the functional interface override the public method of
java.lang.Object
, they also don’t violate the functional interface contract. Check above example, where we have overriddenequals()
andhashCode()
methods
4. Use of Functional Interfaces in Java
Now, we learned about the functional interfaces, but there may be a question in your mind “What can we do with functional Interfaces?”. The answer is with our understanding of the lambda expressions and how they work:
- Lambda expression let us provide implementation of the abstract method defined in the interface directly.
- This implementation is inline, and complete expression is an instance of functional interface.
- The concept is very similar to the anonymous inner classes
Let’s see the following example to understand how functional interfaces can be used in Java.
//using lambda expression
Runnable run = () - > System.out.println("how functional interface works");
// Anonymous inner class
Runnable innerRun = new Runnable() {
public void run() {
System.out.println("Anonymous inner class");
}
};
5. Functional Interfaces Type
The declaration of a functional interface allows a functional interface type to be used in a program by the developer, and these are segregated as four kinds of functional interface type based on a declaration.
- The type of a non-generic function interface.
- A parameterized type (Read More)
- The raw type ( Read More)
- An intersection type (Read More)
Another interesting part is Interface can extend another interface and In this scenario, Interface extending in functional and it doesn’t declare any new abstract methods then the new interface is functional which will satisfy the definition.
public interface Bank {
public void openAccount();
}
Account interface extends Bank interface which has only one OpenAccount method and Account interface doesn’t have any abstract method but still, it is valid functional Interface.
@FunctionalInterface
public interface Account extends Bank {}
Let see one more example, consider while inherits two abstract which have the same signature.
public interface SocialMedia {
public void OpenAccount();
}
Here still the inherited methods logically represent a signal method, so Account is a function interface.
@FunctionalInterface
public interface Account extends SocialMedia {
}
Consider the above example, if one is return type substitutable then Account causes compile time error because it’s inheriting two methods.
interface Bank {public void OpenAccount();}
interface SocialMedia {public boolean OpenAccount();}
There are numbers of functional interfaces defined under java.util.function
package, some useful interfaces are
- Consumer
- Function
- Supplier
- Predicate
5.1 Predicate Example
import java.util.function.Predicate;;
/**
*/
public class PredicateTestExample {
public static void main(String[] args) {
Predicate<String> i = (name) -> name.contains("java");
System.out.println(i.test("Thank you for Learning from javadevjournal.com"));
}
}
5.2 Pass Function Example
import java.util.function.Function;
public class PassFunction {
public static void main(String[] args) {
int percentage = 5;
String result = calc((amount) -> "Tax : " + ((amount * 100) / percentage), 10);
System.out.println(result);
}
public static String calc(Function<Float, String> bi, float i) {
return bi.apply(i);
}
}
Summary
In this post, we got an introduction to the Functional Interfaces in Java 8. We covered some aspects of functional interfaces along with few interesting functional interfaces introduced in Java 8. If you are starting with Java 8, read our following articles on Java 8
Comments are closed.