An interface with only single abstract method is called functional interface. A functional interface can contain default and static methods which do have an implementation in addition to single unimplemented method.
Functional interface acts as a type for lambda expression and can be used to invoke lambda expression
@FunctionalInterface
annotation is added to declare interface as functional interface.- Use of
@FunctionalInterface
annotation is not compulsory for a functional interface, but use of@FunctionalInterface
annotation helps in preventing additional abstract method accidentally. - Adding additional abstract method in an interface declared with
@FunctionalInterface
annotation will result in compilation error.
There are some predefined Functional interfaces in Java. Following are some examples with their single abstract methods:
Interface | Single Abstract Method |
public interface Consumer<T> | void accept(T t) |
public interface Function<T,R> | R apply(T t) |
public interface Predicate<T> | boolean test(T t) |
public interface Supplier<T> | T get() |
public interface Runnable | void run() |
public interface Callable<V> | V call() |
public interface ActionListener | void actionPerformed(ActionEvent e) |
You can also define a functional interface. For example, following is a functional interface:
interface Foo { public void play(); }
A functional interface can also have default and static methods. For example:
interface Foo { public void play(); default void defaultPlay() { System.out.println("default play method"); } public static void staticPlay() { System.out.println("static play method"); } }
In Java 8, Lambda expressions can represent the instance of a functional interface. For example:
Runnable r1 = () -> System.out.println(“Runnable example”);
@FunctionalInterface annotation
This annotation is used to indicate that an interface type declaration is intended to be a functional interface. As mentioned earlier, using this annotation is not mandatory with an interface intended to be a functional interface.
A functional interface has exactly one abstract method. A functional interface can have any number of default and static methods.
If user tries to add more than one abstract method, compiler will flag Invalid ‘@FunctionalInterface’ annotation message. For example, following interface is an invalid functional interface and will give compilation error. Here we have added another abstract method play2().
@FunctionalInterface interface Foo { public void play(); public void play2(); default void defaultPlay() { System.out.println("default play method"); } public static void staticPlay() { System.out.println("static play method"); } }
Functional interface with respect to inheritance
Case 1. If an interface extends functional interface and child interface does not contain any abstract method, then child interface is a functional interface.
In the following example, Child interface extends Parent interface. Child interface does not have its own method. So Child interface is a valid functional interface.
interface Parent { public void play(); } @FunctionalInterface interface Child extends Parent{ }
Case 2: If an interface extends functional interface and child interface defines the exact abstract method, then child interface will be a valid functional interface.
In the following example, child interface defines the same play() method. So child interface has only one abstract method, i.e. play(). So child interface is a valid functional interface.
interface Parent { public void play(); } @FunctionalInterface interface Child extends Parent{ public void play(); }
Case 3: If an interface extends functional interface and child interface defines an additional abstract method then child interface is not a valid functional interface. However, child interface is a valid interface as it is possible for an interface to extend another interface.