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
@FunctionalInterfaceannotation is added to declare interface as functional interface.- Use of
@FunctionalInterfaceannotation is not compulsory for a functional interface, but use of@FunctionalInterfaceannotation helps in preventing additional abstract method accidentally. - Adding additional abstract method in an interface declared with
@FunctionalInterfaceannotation 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.
