CORE JAVA

Functional Interface

Published on

Table of Contents

What is Functional Interface ?

In Java, functional Interface is used  by developers to write expressive, concise & efficient code that helps them to handle complex operation easily.

In this article, we will learn the  concept of Functional Interfaces in Java & understand their characteristics by examples, and explore the way that  how to effectively we can use this  in our day to day coding.

				
					interface  Bank{

    void account();

    default String getName(String bCode){

        return bCode;
    }

    public static void branchName(String ifsc){

        System.out.println(ifsc);
    }

}
				
			

As we can see in the above example, there is only one abstract method along with static & default method. Number of abstratc method is only restriction to be declare an interface as a Functional Interface. We can decalre any number of static & default method.

@FunctionalInterface annotation in Java

Java 8 introduced @FunctionalInterface annotation that wokrks as a marker interfaces which are designed to be functional interfaces. As we know that Functional Interface contains only one Abstract method &  this annotation @FunctionalInterface insures  reinforces this constraint. The  compiler give an error if we try to put another abstract method. By doing so, it maintain the integrity of functional programming principles.

 

Compiler throw the error (unexpected @FunctionalInterface annotation)  if it founds more than one abstarct method .

If there is no abstract found in the annotated function interface, compiler give an error  ” Unexpected @FunctionalInterface annotation

no abstract method found in interface”

 

Conclusion: If any interface is annotated as @FunctionalInterface, there must be one abstract method exist.

Functional Interface In Inheritance

CASE 1: 

If an interface does not have any abstract method and extends Functional Interface then child interface is always treated as Functional interface. Because of inheritance, Parent class abstratc method is by default available in child interface.

				
					@FunctionalInterface
interface  Bank{
    void account();
}

@FunctionalInterface
interface  Branch extends Bank{

}
				
			

Case 2:

Parent interface abstarct method is by default available in child interface but if we want we can define exact same abstract method in child interface as well.

				
					  @FunctionalInterface
    interface  Bank{
        void account();
    }

    @FunctionalInterface
    interface  Branch extends Bank{
        void account();
}
				
			

Case 3:

We will get compile time error if we try to define any new method in child interface (except the abstratct method in parent). The exact compile time error will be

Unexpected @FunctionalInterface annotation

  controllers.Branch is not a functional interface

    multiple non-overriding abstract methods found in interface controllers.Branch

@FunctionalInterface

				
					 @FunctionalInterface
    interface  Bank{
        void account();
    }

    @FunctionalInterface
    interface  Branch extends Bank{

        void brachAddress();
}

Unexpected @FunctionalInterface annotation
  controllers.Branch is not a functional interface
    multiple non-overriding abstract methods found in interface controllers.Branch
@FunctionalInterface
				
			

Case 4:

We can define different method in the child interfacein case if child interface is not declare as a @FunctionalInterface 

				
					@FunctionalInterface
    interface  Bank{
        void account();
    }
    interface  Branch extends Bank{

        void brachAddress();
  }
				
			

Invoking Lambda Expression using Functional Interface

1: Functional Interface is used to invoke lambda expression.

2: Its method contain only singlr abstract method (SAM)

3: It act as a type of Lambda expression

for ex   Runnable r=()-{System.out.println(“thread”)};

here lambda expression on right hand side is type of Runnable

4: There is no restriction of defining number of static & default method in functional interface

Let’s attempt to call the method  of an interface both with and without using a lambda expression, allowing us to gain a clearer understanding of benefit of using Lambda expression.

Wihout Lanbda Expression

 In order to call the method which is define in interface, we need on more class which implements interface..

Here we have an interface called Bank and one class name Demo which implements Bank interface.

				
					public class Main {

    public static void main(String[] args) {

        Bank b=new Demo();
        b.account();;
    }
}
@FunctionalInterface
interface Bank {
    void account();
}

class Demo implements Bank {
    @Override
    public void account() {
        System.out.println("Method Invocation Without Lambda Expression");
    }
}
				
			
				
					Output:Method Invocation Without Lambda Expression
				
			

By Using Lambda Expression

Here, we don’t need any extra class that implement Bank interface to invoke interface method. We can reduce line of code and can get the same output using lamba expression.

				
					public class Main {

    public static void main(String[] args) {

        Bank b=()-> System.out.println("Method Invocation with Lambda Expression");
        b.account();

    }
}
@FunctionalInterface
interface Bank {
    void account();
}
				
			
				
					Output: Method Invocation with Lambda Expression
				
			

Use of Lambda Expression in Collection

1: List

In the above example we have seen how lambda expression can make the code  simple and concise. Lets try to use lambda expression with collection for sorting the obejct.

Here, we have a simple POJO class name Student having three attribute , id, name, and stipend_amount. By using lambda expression, we will sort the object by id, name & stipend_amount.

 

				
					import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {

    public static void main(String[] args) {

        List  list=new ArrayList();

        list.add(new Student(1,"gavin",2000));
        list.add(new Student(7,"alex",8000));
        list.add(new Student(6,"emily",1000));
        list.add(new Student(3,"frank",7000));
        list.add(new Student(5,"devin",12000));
        list.add(new Student(4,"batman",6000));
        list.add(new Student(2,"charly",14000));


        //Sorting by id
         Collections.sort(list,(I1,I2)->(I1.getId()>I2.getId())?1:(I1.getId()I1.getName().compareTo(I2.getName()));
        // Sorting by stipend_amount
        //Collections.sort(list,(I1,I2)->(I1.getStipend_amount()>I2.getStipend_amount())?1:(I1.getStipend_amount()
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-53b9397" data-id="53b9397" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
						<div class="elementor-element elementor-element-6c4b6d3 elementor-widget elementor-widget-heading" data-id="6c4b6d3" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h4 class="elementor-heading-title elementor-size-default">2: Set</h4>		</div>
				</div>
					</div>
		</div>
					</div>
		
				<section class="elementor-section elementor-top-section elementor-element elementor-element-165281f elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="165281f" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-9a23c9c" data-id="9a23c9c" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
						<div class="elementor-element elementor-element-a40f675 elementor-widget elementor-widget-text-editor" data-id="a40f675" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>By default, TreeSet sorts numbers in ascending order(Default Natural Sorting Order). However, we can leverage the Comparator interface( Functional Interface), to sort TreeSet elements in descending order using lambda expression.</p>						</div>
				</div>
					</div>
		</div>
					</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-d53c0e9 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="d53c0e9" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-22a1923" data-id="22a1923" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
						<div class="elementor-element elementor-element-46da9db elementor-widget elementor-widget-code-highlight" data-id="46da9db" data-element_type="widget" data-widget_type="code-highlight.default">
				<div class="elementor-widget-container">
					<div class="prismjs-default copy-to-clipboard ">
			<pre data-line="" class="highlight-height language-javascript line-numbers">
				<code class="language-javascript">
					<xmp>import java.util.Set;
import java.util.TreeSet;

public class TreeSetMain {
    public static void main(String[] args) {

        Set val=new TreeSet&lt;&gt;((I1,I2)-&gt;(I1&gt;I2?-1:(I1
				
			
				
					Output:

[4, 3, 2, 1, 0]
				
			

3: Map

Map is used if we need a group of object as a Key-Value pair. Default natural sorting order is done on the basis of Key. Lets try to use TreeMap to change the default sorting order behavior by using Comparator interface (Functional interface).

 

				
					import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapMain {
    public static void main(String[] args) {

        // Default Natural sorting
       // Map tm=new TreeMap();

        // Sorting by passing Comparator object in constructor
         Map tm=new TreeMap((I1,I2)-&gt;(I1&gt;I2)?-1:(I1 en:tm.entrySet()){
            System.out.println(en.getKey()+" "+en.getValue());
        }


    }
}

				
			
				
					Output:

5 .Net
4 Scala
3 Php
2 React
1 Java
				
			

Difference between Anonymous inner class and Lambda expression

1: It is a class without name

2: Anonymous inner class can extend concrete and abstract class 

3: Anonymous inner class can contain more than one abstract method.

4: Anonymous inner class can have instance variable.

5: In Anonymous inner class, this (current class object) always refer current Anonymous inner class but not outer class object.

6: In Anonymous inner class, on demand memory allocated once we create an object

1: It is a function without name

2: Lambda expression  can not extend any concrete and abstract class.

3: Lambda expression is only used for an interface which have single one abstract method (SAM)  i.e. Runnable interface (Functional Interface)

4: In Lambda expression we can not declare any instance variable. If we declare any variable, it will be treated as local variable.

5: Inside Lambda expression, this always refer current outer class Object

6: Lambda expression is reside in permanent memory of JVM i.e method area

On the basis of these differences we can say that Anonymous inner class is different  and behave differently in most of the cases. 

Advantages of Lambda Expression

Difference between interface with default method of abstract class

Interface with default method

Abstract class

1: Every variable  is public static & final in interface and we can not declare any instance variable

2: Interface never talks about state of object

3: We can not declare constructor inside interface.

4: Instatce and static block declareation is not possible in inside interface.

5: Functional interface with default method can refer lambda expression.

6: Inside inerface, we can not override Object class mehod

1: In abstract class we can decalre instance variable which are required in the implemened class.

2: Abstract class can  talk about state of object

3: In Abstract class we can declare constructor.

4: We can declare static and instance block in Abstract class.

5: Abstract class can not refer lambda expression. 

6: Inside abstract class we can override Object class method

Popular Posts