Functional Interfaces in Java

Naveen AnamaneniUpdated · 4 min read

A functional interface in Java is an interface that has exactly one abstract method. It is used as the type of a lambda expression or method reference: the lambda provides the body of that one method. Examples you already know are Runnable (run), Comparator (compare) and Comparable (compareTo). A functional interface may also have any number of default and static methods. In this lesson, you will learn the rules of functional interfaces, the @FunctionalInterface annotation, and how to write your own.

Syntax

Syntax
@FunctionalInterface
interface Validator {
    boolean isValid(String input);   // the single abstract method
}

Rules of a Functional Interface

  • Exactly one abstract method. This method is sometimes called the SAM (single abstract method).
  • Default and static methods are allowed in any number, because they already have bodies.
  • Methods of Object (such as equals and toString) declared in the interface don't count, because every class already has them.
  • @FunctionalInterface is optional, but recommended: the compiler then reports an error if someone adds a second abstract method.

Example: Your Own Functional Interface

Let's see an example of a validator implemented with lambdas.

Validators.java▶ Try it
public class Validators {
    @FunctionalInterface
    interface Validator {
        boolean isValid(String input);
 
        default Validator and(Validator other) {
            return s -> isValid(s) && other.isValid(s);
        }
    }
 
    public static void main(String[] args) {
        Validator notEmpty = s -> !s.isEmpty();
        Validator shortName = s -> s.length() <= 8;
        Validator both = notEmpty.and(shortName);
 
        for (String name : new String[] {"Navika", "", "Anamaneni"}) {
            System.out.println("\"" + name + "\" valid? " + both.isValid(name));
        }
    }
}
Output
"Navika" valid? true
"" valid? false
"Anamaneni" valid? false

Explanation: Validator has one abstract method, isValid, so lambdas can implement it. The default method and combines two validators into a new one. An empty name fails notEmpty, and "Anamaneni" has 9 letters, so it fails shortName.

What @FunctionalInterface Checks

If an interface marked @FunctionalInterface gets a second abstract method, the compiler stops you:

Broken.java
@FunctionalInterface
interface Broken {
    void first();
    void second();
}
Compiler output
Broken.java:1: error: Unexpected @FunctionalInterface annotation
@FunctionalInterface
^
  Broken is not a functional interface
    multiple non-overriding abstract methods found in interface Broken
1 error

Explanation: Broken has two abstract methods, so a lambda couldn't know which one to implement. The annotation turns this mistake into a compile error at the interface itself.

Common Functional Interfaces in the JDK

InterfaceMethodPackage
Runnablevoid run()java.lang
Comparable<T>int compareTo(T o)java.lang
Comparator<T>int compare(T a, T b)java.util
Callable<V>V call()java.util.concurrent
Predicate<T>, Function<T, R>, Consumer<T>, Supplier<T>...One method eachjava.util.function

Common Mistakes

Adding a second abstract method to an interface that lambdas use. Every lambda for it stops compiling; @FunctionalInterface catches this early.

Thinking equals counts as an abstract method. Methods inherited from Object don't count.

Thinking the annotation is required. Any interface with one abstract method works with lambdas.

Interview Corner

What is a functional interface?

An interface with exactly one abstract method, which makes it a valid target type for lambda expressions and method references. It can have any number of default and static methods, and abstract methods that match public methods of Object don't count. The @FunctionalInterface annotation is optional but makes the compiler verify the rule. Examples are Runnable, Comparator, Callable and the interfaces in java.util.function.

Practice

  1. Easy: Write a functional interface Discount with double apply(double price) and lambdas for 10% off and a flat 50 off.
  2. Harder: Add a default method then(Discount next) that applies this discount and then the next one, and test it.

Quick check: Functional interfaces

4 questions
1How many abstract methods does a functional interface have?
2Can a functional interface have default methods?
3What does @FunctionalInterface do?
4Which is a functional interface?

Key Takeaways

Was this tutorial helpful?

Lesson 306 of 482