Java 8 – Functional Interfaces

Today I´d like to give you a short overview above functional interfaces in Java.

We are able to define and work with functional interfaces since the release of Java 8. But why should you use this interfaces and what are their major benefit?
To answer this first question, have a look at the Functional Interface Documentation of Oracle.

Functional interfaces provide target types for lambda expressions and method references.
Quote: Java Doc Functional Interface

As you can see, we use (or can use) functional interfaces perfectly for lambda expressions. But that´s not their only purpose.
If you may have worked with Threads in Java you are familiar with the Runnable Interface. 
If we have a closer look at this interface we can see, that it provides only one method. The run method. And that´s also the definition of a functional interface.

A interface that only provides one abstract method is called a functional interface.
But you can add as many default methods to your interface as you want.

That sounds quite right doesn´t it?
But maybe you have heard, that a functional interfaces only becomes one, if it is annotated with @FunctionalInterface? – It´s wrong. Sorry Bro.

Annotating an interface with @FunctionalInterface will mark this interface as a functional one for sure. That´s right. But it´s just a “marker” for you, the compiler and some code quality tracking tools. So we can say, that this annotation is not mandatory.

Own functional interface

After we have talked about the theories behind the functional interfaces, let´s setup a simple interface for example like this:

public interface Addition {

    int addTwoNumbers(int x, int y);
}

As you can see, the interface Addition only provides one method.
(They keyword abstract and the access modifier don´t have to be written, because every method in an interface – except default methods – are abstract by default.) 

We haven´t wrote the annotation @FunctionalInterface. If you want to, you can do that.

The most common way, why you could annotate your functional interface with @FunctionalInterface is, to tell all other developers working with taht code, that they are not allowed to add methods to this interface

Use the functional interface

After we have declared the functional interface, we now can use it.

For this, we have to override the method provided by the interface and give it to an instance of the interface.

public static void main(String[] args) {

    int firstNumber = 5;
    int secondNumber = 6;

    //Overrides the method
    Addition addition = (int first, int second) -> first + second;

    //Uses the overriden method
    int result = addition.addTwoNumbers(firstNumber, secondNumber);

    System.out.println(result);

}

As you can see:

  • We are declaring two variables firstNumber and secondNumber 
  • Then we override the functional method
  • We use the overriden method to perform our implementation

Failure on two methods

Try to add another method to your functional interface. The interface will still compile. But your implementation in the main method will fail because the compiler will find multiple methods that aren´t overriden.

If you annotate your Addition interface with @FunctionalInterface like this

@FunctionalInterface
public interface Addition {

    int addTwoNumbers(int x, int y);

}

and you would add another method to this interface, you´ll see the benefit of this annotation.
Your interface won´t compile successfully anymore.

Default Methods

If you still want to have more methods in your interface, you need to mark them as default. This works fine for as many methods as you want to.

@FunctionalInterface
public interface Addition {

    int addTwoNumbers(int x, int y);


    default int substract(int x, int y) {
        return x - y;
    }

    default int multiply(int x, int y) {
        return x * y;
    }
}

Predicate Interface

There are a lot of nice ideas for functional interfaces out there. But for me, one of the best functional interface is the Predicate API.

A Predicate is a functional interface that contains the abstract method test(T t) and some default methods.

Predicates help you to handle the conditions or even the proofing process in your implementations.

Example

Let´s have short look at the following example.

We want to check if any input number to our method is dividable by two or if it is an odd number. Before you start reading the code, think about how you would do that in the “old way“. You have to deal around with an if statement, in which you return true if it is dividable by two otherwise you would return false. Of course this is not a lot of code, but it´s still more than the thing we will write now:

Integer number = 20;

Predicate<Integer> dividableByTwo = (Integer y) -> y % 2 == 0;

System.out.println(dividableByTwo.test(number));

What have we done?

  • We have our input parameter
  • We override the parameterized Predicate API with our modulo operation
  • We print out the result (true or false)

Conclusion

Now you can write simple and elegant little pieces of code with the use of functional interfaces. You have learned about what function interfaces are in theory and what they are not. We had a look on how to break with this principle and what is allowed in a functional interface. After that we wrote our own little interface and finally we used the Predicate API to look at a other example.

 

So thank´s for reading and have fun using functional interfaces.

 

Feel free to share

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.