1.2.  Describe and write functional interfaces

[Note]

Functional interfaces provide target types for lambda expressions and method references. Each functional interface has a single abstract method (SAM), called the functional method for that functional interface, to which the lambda expression's parameter and return types are matched or adapted.

All the existing single method interfaces like Runnable,Callable, Comparator, and ActionListener in the JDK 8 are now functional interfaces and lambdas can be used anywhere a single abstract method interface is used.

@FunctionalInterface annotation

Java 8 have introduced a new annotation @FunctionalInterface to mark an interface as such. It's basically to communicate intent but also allows the compiler to do some additional checks.

[Warning]

The @FunctionalInterface annotation is optional, it is a "hint" for Java compiler.

For example, this interface compiles successfully:

public interface MyInterface {
}
					

But when you indicate that it should be a functional interface:

// Java 8 compiler fails
@FunctionalInterface
public interface MyInterface {
}
					

The compiler will raise an error as there is no abstract method. It says that "MyInterface is not a functional interface" as "no abstract method was found". It will also error if we try and add a second method:

// Java 8 compiler fails !
@FunctionalInterface
public interface MyInterface {
    void doIt();
    void doItNow();
}
					

Default methods in interfaces

In Java 8 interfaces support default and static methods. A default method is an instance method defined in an interface whose method header begins with the default keyword; it also provides a code body. Every class that implements the interface inherits the interface's default methods and can override them.

Since functional interface requires a single abstract method, this code will NOT compile, as it is invalid functional interface:

// Java 8 compiler fails !
@FunctionalInterface
public interface MyDefInterface {
    default void doIt() { /* cool implementation */ }
}
					

But this functional interface will compile successfully:

@FunctionalInterface
public interface MyDefInterface {
    default void doIt() { /* cool implementation */ }
    void doItNow(); // Single Abstract Method (SAM)
}
					

Static methods in interfaces

A static method is a method that's associated with the class in which it's defined, rather than with any object created from that class. Every instance of the class shares the static methods of the class. Java 8 also lets static methods be defined in interfaces where they can assist default methods.

Like static methods in classes, you specify that a method definition in an interface is a static method with the static keyword at the beginning of the method signature. All method declarations in an interface, including static methods, are implicitly public, so you can omit the public modifier.

When you implement an interface that contains a static method, the static method is still part of the interface and not part of the implementing class. For this reason, you cannot prefix the method with the class name. Instead, you must prefix the method with the interface name.

Since functional interface requires a single abstract method, this code will NOT compile, as it is invalid functional interface:

// Java 8 compiler fails !
@FunctionalInterface
public interface MyStatInterface {
    static void doIt() { /* cool implementation */ }
}
					

But this functional interface will compile successfully:

@FunctionalInterface
public interface MyStatInterface {
    static void doIt() { /* cool implementation */ }
    void doItNow();
}
					

Public methods of java.lang.Object in functional interfaces

If an interface declares an abstract method overriding one of the public methods of java.lang.Object, that also DOES NOT count toward the interface's abstract method count since any implementation of the interface will have an implementation from java.lang.Object or elsewhere.

For example, java.util.Comparator is a functional interface even though it declared two abstract methods:


package java.util;

@FunctionalInterface
public interface Comparator<T> {

    int compare(T o1, T o2);

    boolean equals(Object obj);

    ...
}

					

The reason is because one of these abstract methods - equals() - has signature identical to public method in java.lang.Object class.

Professional hosting         Free 'Oracle Certified Expert Web Services Developer 6' Guide     Exam 1Z0-810: Upgrade to Java SE 8 Programmer Quiz