In this article, we will discuss about new features introduced in Java 1.8 version i.e.; Functional Interface
What is Functional Interface ?
- An interface which contains only one abstract method is called as Functional interface
Why we need Functional Interface ?
- Another feature introduced in Java 1.8 version is Lambda Expression
- To invoke/call this lambda expression we need Functional Interface
Rules for Functional Interface :
- As mentioned earlier above, Functional Interface can have maximum of only one abstract method
- In short, it is called as Single Abstract Method i.e.; SAM
- In addition to one abstract method, we can have any number of static or default methods, another feature added in Java 1.8 version
- An optional annotation @FunctionalInterface can be annotated for Functional Interface to make sure that not more than one abstract method is declared
- If more than one abstract method declared and also annotated with @FunctionalInterface, then compiler throws error
- Note: To invoke Lambda Expression we need Functional Interface and it is must
Few valid and invalid scenarios w.r.t Inheritance
Let us understand with example for Functional Interface
- ParentInterface is valid because we have only one abstract method declared
- So, here we are checking/verifying valid/invalid scenarios for ChildInterface
package net.bench.resources.java8; @FunctionalInterface public interface ParentInterface { public void display(); }
Valid scenario 1:
@FunctionalInterface interface ChildInterface extends ParentInterface{ // no more abstract methods declared // any number of static and default methods }
- ChildInterface inherits but no more abstract method is declared
- But can have any number of static and default methods
- Note: Both parent interface & child interface is annotated with @FunctionalInterface
Valid Scenario 2:
@FunctionalInterface interface ChildInterface extends ParentInterface{ // same abstract methods re-declared public void display(); // any number of static and default methods }
- ChildInterface inherits but same abstract method is re-declared
- But can have any number of static and default methods
- Note: Both parent interface & child interface is annotated with @FunctionalInterface
Valid Scenario 3:
interface ChildInterface extends ParentInterface{ // one more abstract method declared public void sum(); // any number of static and default methods }
- There is no @FunctionalInterface annotation in ChildInterface
- Therefore it will act as normal interface in Java with additional abstract methods
- Note: Only parent interface annotated with @FunctionalInterface so we can add any number of abstract methods in child interface as there is no @FunctionalInterface annotation
Invalid scenario 1:
@FunctionalInterface interface ChildInterface extends ParentInterface{ // one more abstract method declared public void sum(); // any number of static and default methods }
- Compile time error – Invalid ‘@FunctionalInterface’ annotation; ChildInterface is not a functional interface
- Now ChildInterface contains 2 methods, one inherited from ParentInterface and another declared in ChildInterface
- Note: Both parent interface & child interface is annotated with @FunctionalInterface
Example for Functional Interface along with Lambda Expression:
Example 1: To find cube of any Integer
package net.bench.resources.java8; @FunctionalInterface interface DemoInterface { public int cube(int i); } public class TestLambdaExpression { // main method public static void main(String[] args) { // Lambda Expression DemoInterface d = (i) -> i*i*i; // how to invoke Lambda Expression -> Functional Interface System.out.println(d.cube(7)); } }
Output:
343
Example 2: To multiply any two Integer
package net.bench.resources.java8; @FunctionalInterface interface DemoInterface { public int multiply(int i, int j); } public class TestLambdaExpression { // main method public static void main(String[] args) { // Lambda Expression DemoInterface d = (i, j) -> i*j; // how to invoke Lambda Expression -> Functional Interface System.out.println(d.multiply(7, 21)); } }
Output:
147
Example 3: To find substring of last 3 characters
package net.bench.resources.java8; @FunctionalInterface interface DemoInterface { public String substring(String s); } public class TestLambdaExpression { // main method public static void main(String[] args) { // Lambda Expression DemoInterface d = (s) -> s.substring((s.length()-3), s.length()); // how to invoke Lambda Expression -> Functional Interface System.out.println(d.substring("BenchResources.Net")); } }
Output:
Net
Example 4: To print Hello World
package net.bench.resources.java8; @FunctionalInterface interface DemoInterface { public void print(); } public class TestLambdaExpression { // main method public static void main(String[] args) { // Lambda Expression DemoInterface d = () -> System.out.println("Hello World");; // how to invoke Lambda Expression -> Functional Interface d.print(); } }
Output:
Hello World
So far, whatever Functional Interface we have seen is all custom for our purposes. In this way, we will creating lot of redundant code whose purpose will be very similar. To address this, Java 1.8 version comes with couple of Pre-defined Functional Interface as listed below,
- Pre-defined Functional Interface (1 argument)
1. Predicate
2. Function
3. Consumer
4. Supplier - Pre-defined Functional Interface (2 arguments)
1. BiPredicate
2. BiFunction
3. BiConsumer - Primitive Predicate Functional Interface
- Primitive Function Functional Interface
- Primitive Consumer Functional Interface
- Primitive Supplier Functional Interface
- UnaryOperator Functional Interface
- BinaryOperator Functional Interface
References:
- https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
- https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html
- https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html
- https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
Happy Coding !!
Happy Learning !!