Functional Interfaces in Java

functional interfaces in java

You’ve probably heard of a functional interface before, often in the same breath as lambdas. What are functional interfaces, and why are they used with lambdas?

Lambdas and functional interfaces go hand in hand in Java.

A functional interface is simply an interface that has a single abstract method. Before Java 8, they were referred to as SAM interfaces.

Why are these interfaces so important that they have their own term? Two reasons:

  1. Good design.
    The “I” in the SOLID design principles refers to the Interface Segregation Principle. This states that many small interfaces are better than one large general purpose interface. Clients shouldn’t be forced to implement interfaces they don’t use. So functional interfaces are the ultimate small interface.
  2. Lambdas.
    The only way the compiler can infer which method you’re trying to implement with a lambda expression is that there is only a single method that you can implement.

Quick recap

Let’s revisit the Comparator example from the previous post.

Using the anonymous inner class code, it’s obvious what you’re doing: you’re implementing the compare() method:

// use an anonymous inner class to create a Comparator object
TreeSet ts = new TreeSet<>(
        new Comparator() {
            @Override
            public int compare(Employee e1, Employee e2) {
                return e1.getAge() - e2.getAge();
            }
        }
    );

But when you’re using a lambda expression, what can the compiler infer? The only way it can work out what you’re trying to do, is if you’re only allowed to implement a single method.

// use an lambda to create a Comparator object

TreeSet ts = new TreeSet<>(
         (Employee e1, Employee e2) -> { 
                  return e1.getAge() - e2.getAge(); }
    );

The Comparator interface is a functional interface, with the compare() method being the only abstract method.

@FunctionalInterface annotation

The @FunctionalInterface annotation marks the interface as a functional interface. It forces the compiler to check that there is only one abstract method.

At first this seems unnecessary. Interfaces are usually very small Java classes and it should be easy to just see what’s in the interface. But from Java 8, we’re allowed to have implemented methods in an interface. These are static and default methods. If there are a lot of methods, it is difficult for a programmer to check that they only have one abstract method, or haven’t forgotten to implement a method appropriately.

For example:

@FunctionalInterface
public interface MyInterface {
    public void foo(); // single abstract method

    // default instance method - can be overridden if needed
    public default void bar() {
        // appropriate code
    }

    // static class method - called as MyInterface.baz() 
    public static void baz() {
       // appropriate code
    }
}

Functional interfaces as targets for lambda expressions

As a general rule, you can’t reuse lambda expressions. If you pass a lambda expression to a method, you would usually copy-and-paste it if you wanted to use it again.

Functional interfaces to the rescue! Variables of functional interface types can be used as targets for lambda expressions. This means that you can assign a lambda expression to a variable, as long as that variable’s type is a functional interface.

Revisiting the Comparator example, we can reuse the lambda expression easily if we assign it to a functional interface type:

Comparator cmp1 = (Employee e1, Employee e2) -> { 
                     return e1.getAge() - e2.getAge(); }

Comparator cmp2 = (e1, e2) -> { 
                     return e1.getAge() - e2.getAge(); }

Comparator cmp3 = (e1, e2) -> 
                     e1.getAge() - e2.getAge();

TreeSet ts = new TreeSet<>(cmp3);

I’ll cover the default and static methods of Comparator in a later post.

Leave a Comment

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

Code like a Java Guru!

Thank You

We're Excited!

Thank you for completing the form. We're excited that you have chosen to contact us about training. We will process the information as soon as we can, and we will do our best to contact you within 1 working day. (Please note that our offices are closed over weekends and public holidays.)

Don't Worry

Our privacy policy ensures your data is safe: Incus Data does not sell or otherwise distribute email addresses. We will not divulge your personal information to anyone unless specifically authorised by you.

If you need any further information, please contact us on tel: (27) 12-666-2020 or email info@incusdata.com

How can we help you?

Let us contact you about your training requirements. Just fill in a few details, and we’ll get right back to you.

Your Java tip is on its way!

Check that incusdata.com is an approved sender, so that your Java tips don’t land up in the spam folder.

Our privacy policy means your data is safe. You can unsubscribe from these tips at any time.