12 Java - Interfaces (Functional & Lambda)

Chetan DattaChetan Datta
4 min read

What is Functional Interface?

  • If an interface contains only 1 abstract method, that is known as Functional Interface.

  • Alos known as SAM interface (Single Abstract Method).

  • @ FunctionalInterface keyword can be used at top of the interface(But its optional)

@FunctionalInterface
public interface Bird {
    void canFly(String val);
}

OR

public interface Bird {
    void canFly(String val);
}
  • @ FunctionalInterface Annotation restrict us and throws compilation error, if we try to add more than 1 abstract method.

  • In Functional Interface, only 1 abstract method is allowed, but we can have other methods like default, static method or Methods inherited from the object class.
@FunctionalInterface
public interface Bird {
    void canFly(String val);

    default void getHeight(){
        //default method implementation
    }

    static void canEat(){
        // my static method implementation
    }

    String toString(); // Object class method
}
public interface TestInterface {
    String toString();
}

// No need to implement toString because
//Object class already implemented
public class TestClassImplements implements TestInterface{
}

What is Lambda Expression?

  • Lambda expression is a way to implement the Functional Interface.

  • Lambda expression is introduced because of functional interface.

Before going into further into Lambda expression, lets first see:

3 Ways to Implement the Functional Interface

@FunctionalInterface
public interface Bird {
    void canFly(String val);
}

Using "implements"

public class Eagle implements Bird{
    @Override
    public void canFly(String val) {
        System.out.println("Eagle Bird implementation");
    }
}
Bird eagleObject = new Eagle();
eagleObject.canFly();

Using "anonymous Class"

public class Main {
    public static void main(String[] args) {
        Bird eagleObject = new Bird() {
            @Override
            public void canFly(String val) {
                System.out.println("Eagle Bird Implementation");
            }
        };

        eagleObject.canFly("cool");
    }
}

Using "Lambda Expression"

public class Main {
    public static void main(String[] args) {
        Bird eagleObject = (String val) -> {
            System.out.println(val);
        };

        eagleObject.canFly("Cool");
    }
}

Types of Functional Interface

Consumer

  • Represent an operation, that accept a single input parameter and returns no result.

  • Present in package: java.util.function

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
}

Usage

import java.util.function.Consumer;

public class Main {
    public static void main(String[] args) {
        Consumer<Integer> loggingObject = (Integer val) -> {
            if (val > 10){
                System.out.println("logging");
            }
        };
        loggingObject.accept(11);
    }
}

Supplier

  • Represent the supplier of the result. Accepts no Input parameter but produce a result.

  • Present in package: java.util.function

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

Usage

public class Main {
    public static void main(String[] args) {
        Supplier<String> isEvenNumber = () -> "this is the data I am returning";
        System.out.println((isEvenNumber.get()));
    }
}

Function

  • Represent function, that accepts one argument process it and produce a result.

  • Present in package: java.util.function

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
}
import java.util.function.Function;

public class Main {
    public static void main(String[] args) {
        Function<Integer, String> app = (Integer num) -> {
          String output = num.toString();
          return output;
        };
        System.out.println(app.apply(64));
    }
}

Predicate

  • Represent function, that accept one argument and return the boolean.

  • Present in package: java.util.function;

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
}
import java.util.function.Predicate;

public class Main {
    public static void main(String[] args) {
        Predicate<Integer> isEven = (Integer val) -> {
            if (val%2 == 0)
                return true;
            else
                return false;
        };

        System.out.println(isEven.test(19));
    }
}

Handle use case when Functional Interface extends from other Interface

Use Case 1

Functional Interface extending Non Functional Interface

public interface LivingThing {
    public void canBreathe();
}

Not Possible

Use Case 2

Interface extending Functional Interface

@FunctionalInterface
public interface LivingThing {
    public void canBreathe();
}

public interface Bird extends LivingThing{
    void canFly(String val);
}

Use Case 3

Functional Interface extending other Functional Interface

Not possible

@FunctionalInterface
public interface LivingThing {
    public void canBreathe();
}

@FunctionalInterface
public interface Bird extends LivingThing{
    void canFly(String val);
}

Possible

@FunctionalInterface
public interface LivingThing {
    public boolean canBreathe();
}

@FunctionalInterface
public interface Bird extends LivingThing{
    public boolean canBreathe();
}

Usage

public class Main {
    public static void main(String[] args) {
        Bird eagle = () -> true;
        System.out.println(eagle.canBreathe());
    }
}
0
Subscribe to my newsletter

Read articles from Chetan Datta directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Chetan Datta
Chetan Datta

I'm someone deeply engrossed in the world of software developement, and I find joy in sharing my thoughts and insights on various topics. You can explore my exclusive content here, where I meticulously document all things tech-related that spark my curiosity. Stay connected for my latest discoveries and observations.