Tech with Maddy

Tech with Maddy

Java 8: Functional Interfaces

Java 8: Functional Interfaces

Subscribe to my newsletter and never miss my upcoming articles

In this article we are going to cover the following points:

  • What is a functional interface.
  • Why do we need a functional interface.
  • How to create a functional interface.
  • Few notes to keep in mind about functional interfaces.

Ready? Let's go!

WHAT IS A FUNCTIONAL INTERFACE

A functional interface is an interface that contains only a single abstract method (a method that doesn’t have a body). The main reason why we need functional interfaces is that we can use them in a lambda expression and method references. This way we reduce boilerplate code.

You don’t have to include the abstract keyword, because by default a method declared inside a functional interface is abstract. Only one abstract method is allowed, but it accepts multiple default and static methods.

WHY DO WE NEED A FUNCTIONAL INTERFACE

The main reason is that without a functional interface we would have to use an Anonymous class, which is not that bad, but functional interfaces make the code more straightforward to read. For example, an anonymous class is created like this:

public class AnonymousClassExample {

    public static void main(String[] args) {

        Thread thread = new Thread(){
            public void run(){
                System.out.println("Understanding what is an anonymous class");
            }
        };
        thread.start();
    }
}

Here we have used the Thread class to create an object and print out a message when we start the thread. The outcome is:

Understanding what is an anonymous class

If instead, we use a functional interface, we can reduce the lines of code that we write and increase its readability.

public class AnonymousClassExample {

    public static void main(String[] args) {

        Runnable runnable = () -> {
            System.out.println("Understanding functional interfaces");
        };
        runnable.run();
    }
}

The outcome is:

Understanding functional interfaces

In short, the main benefit of using functional interfaces is that they can be instantiated using lambda expressions, rather than using lengthy anonymous classes.

HOW TO CREATE A FUNCTIONAL INTERFACE

You can either create your own functional interface with the annotation @FunctionalInterface like in Example 1, or use the ones which have already been predefined by Java as seen in Example 2.

EXAMPLE 1

  • We create our own interface called FunctionalInterface with a single abstract method and mark it with the annotation @FunctionalInterface.
  • We have a public class FunctionalInterfaceDemo where we want to execute the method.
  • We use the lambda expression to represent the functional interface. We have two parameters because the method multiplyNumber() has two arguments. It can be read like this: "Given a parameter x and a parameter y, perform the multiplication between the two".
  • We print out the multiplication between 2 and 3.
@java.lang.FunctionalInterface
interface FunctionalInterface{

   public int multiplyNumber(int x, int y);

}

public class FunctionalInterfaceDemo {

   public static void main(String[] args) {

       FunctionalInterface functionalInterface = (x, y) -> x * y;

       System.out.println("The result is: " functionalInterface.multiplyNumber(2, 3));
   }
}

The outcome is:

The result is: 6

EXAMPLE 2

  • We use the predefined functional interface ToDoubleFunction. This functional interface takes an argument T (in our case of type String) and returns a double as a result.
  • All we want to do with our lambda is to return the length of a given parameter.
  • The ToDoubleFunction interface has a single abstract method which is the applyAsDouble() method. In our case, it has the String "Hello Maddy" as a parameter.
  • In the end, we print the length of the message, which is 12.0. Remember that spaces are included.
import java.util.function.ToDoubleFunction;
public class FunctionalInterfaceDemo {

    public static void main(String[] args) {

       ToDoubleFunction<String> length = x -> x.length();

        System.out.println(length.applyAsDouble("Hello Maddy!"));
    }
}

The outcome is:

12.0

FEW NOTES TO KEEP IN MIND ABOUT FUNCTIONAL INTERFACES

  • The @FunctionalInterface annotation is optional. It's just used to ensure that there is only one abstract method.
  • A functional interface cannot extend another functional interface.
  • A functional interface can contain any number of Object class methods.
 
Share this