Functional interfaces have a single functionality to exhibit. For example, a Comparable interface with a single method compareTo is used for comparison purpose
Functional Interface is an interface which has one and only one abstract method. Apart from abstract method, it can have any number of default and static methods which have an implementation and are not abstract and overridden method from Object.These interfaces are also called Single Abstract Method Interfaces. Few Functional Interfaces are Comparable, Runnable and etc.
Example of Functional Interface
@FunctionalInterface public interface MyFunctionalInterface { public void MethodOne(int i, double d); }
@FunctionalInterface public interface MyFunctionalInterface { public void MethodOne(int i, double d); default boolean methodTwo(String value) { return true; } }
@FunctionalInterface annotation is used to mark an interface as Functional Interface
not mandatory to use it. If the interface is annotated with @FunctionalInterface annotation and when we
try to have more than one abstract method, it throws the compiler error.
There are two ways the abstract method definition in the functional interface could be done
One is by Anonymous Inner class and other is by Lambda Expression
For example in Java, if we have to instantiate runnable interface anonymously, then our code looks like below. It’s bulky
Anonymous Inner class way of method definion for Functional Interface
Runnable r = new Runnable(){ @Override public void run() { System.out.println("My Runnable"); }};
lambda expressions for the above method implementation is
Lambda Expressions way of method definion for Functional Interface
Runnable r1 = () -> { System.out.println("My Runnable"); };
Functional interface with abstract method(oneMethod) and default(getMulty), static methods(getSum) which have an implementation and are not abstract and methods overridden from Object Class(toString and equals).
@FunctionalInterface public interface MyFunctionalInterface { public void oneMethod(int i, double d); public String toString(); public boolean equals(Object o); public static int getSum(int a,int b) {// valid->method static return a+b; } public default int getMulty(int c,int d) {//valid->method default return c+d; } }
Functional Interface could be classified into the following 5 Types based on the parameters and the way the abstract method behaves
- Supplier
- Consumer
- Predicate
- Function
- Operator
Functional Interface | Parameter Types | Return Type | Abstract Method Name | Description |
---|---|---|---|---|
Runnable | none | void | run | Runs an action without arguments or return value |
Supplier |
none | T | get | Supplies a value of type T |
Consumer |
T | void | accept | Consumes a value of type T |
BiConsumer |
T, U | void | accept | Consumes values of types T and U |
Function |
T | R | apply | A function with argument of type T |
BiFunction |
T, U | R | apply | A function with arguments of types T and U |
UnaryOperator |
T | T | apply | A unary operator on the type T |
BinaryOperator |
T, T | T | apply | A binary operator on the type T |
Predicate |
T | boolean | test | A Boolean-valued function |
BiPredicate |
T, U | boolean | test | A Boolean-valued function with two arguments |
What is need for Default Method in Functional Interface?
- If we want to add additional methods in the interfaces, it will require change in all the implementing classes.
- As interface grows old, the number of classes implementing it might grow to an extent that its not possible to extend interfaces.
- That’s why when designing an application, most of the frameworks provide a base implementation class and then we extend it and override methods that are applicable for our application.
- “Default Method” or Virtual extension methods or Defender methods feature, which allows the developer to add new methods to the interfaces without breaking their existing implementation. It provides the flexibility to allow interface to define implementation which will use as the default in a situation where a concrete class fails to provide an implementation for that method.
Lets Imagine we have UserDevices which later wants to provide support for blackberry devices at later part of Software release. You cannot have a abstract method for blackberrySupport and make the implementing classes to do method definition.Instead of that I am writing as default method in interface which prevents all the implementing classes to write its own method definition.
public interface UserDevices { default void blackberrySupport(){ System.out.println("Support for Blackberry Devices"); } } public class Device implements UserDevices { }
What if the class implements two interfaces and both those interfaces define a default method with the same signature?
public interface UserDevices1 { default void blackberrySupport(){ System.out.println("Support for Blackberry Devices1"); } } public interface UserDevices2 { default void blackberrySupport(){ System.out.println("Support for Blackberry Devices2"); } } public class Device implements UserDevices1 , UserDevices2 { }
This code fails to compile with the following result:
java: class Device inherits unrelated defaults for blackberrySupport() from types UserDevices1 and UserDevices2
In this case we have to resolve it manually by overriding the conflicting method
public class Device implements UserDevices1, UserDevices2 { public void blackberrySupport(){ UserDevices1.super.blackberrySupport(); } }
The Best Example of Default Method is addition of foreach method in java.util.List Interface.