Java 8 – Functional Interface with examples

In this article, we will discuss about new features introduced in Java 1.8 version i.e.; Functional Interface

Q) What is Functional Interface ?

  • An interface which contains only one abstract method is called as Functional interface

Q) 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

1. 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

2. 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

ParentInterface.java

package net.bench.resources.java8;

@FunctionalInterface
public interface ParentInterface {

	public void display();
}

2.1 Valid scenario 1:

ChildInterface.java

@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

2.2 Valid Scenario 2:

ChildInterface.java

@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

2.3 Valid Scenario 3:

ChildInterface.java

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

2.4 Invalid scenario 1:

ChildInterface.java

@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

3. Example for Functional Interface along with Lambda Expression:

3.1 To find cube of any Integer

TestLambdaExpression.java

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

3.2 To multiply any two Integer

TestLambdaExpression.java

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

3.3 To find substring of last 3 characters

TestLambdaExpression.java

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

3.4 To print Hello World

TestLambdaExpression.java

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,

References:

Happy Coding !!
Happy Learning !!

Java 8 - Anonymous Inner class v/s Lambda Expression
Java 8 - Lambda Expression