Interface
in java contains abstract
methods. Up to Java 7, An Interface
contained only one abstract
method called Single Abstract Method Interface
or SAM
. Those interfaces contain a single functionality.
After java 8
, the Single Abstract Method
or SAM
are also known as Functional Interfaces
. The Functional Interfaces
instances can be used to represent lambda
expressions or method references
. The Functional Interfaces
can have any number of default
methods and static
methods.
The functional Interface helps to achieve functional programming approach
java.lang.Runnable
, java.awt.event.ActionListener
, java.util.Comparator
and java.util.concurrent.Callable
are some Functional interfaces
.
package org.wesome.java8;
interface Apple {
void show();
}
The syntex for Java 8 lambda
is
FunctionalInterface instanceVariable = (input parameters) -> {}
The above program will be converted to Java 8 lambda
as below.
package org.wesome.java8;
interface Apple {
void show();
}
class Fuji {
public static void main(String[] args) {
Apple apple = () -> {
System.out.println("i love Apple");
};
/* since it's a single line method hence input type return and brackets are not required */
Apple apple1 = () -> System.out.println("i love Apple");
apple.show();
apple1.show();
}
}
What is a Functional Interface
A Functional Interface
should have a single abstract
method but can contain multiple static
and default
methods. if multiple abstract
methods are provided, the compiler
will throw an error at execution
time.
package org.wesome.java8;
interface Apple {
void show();
void eat();
static void price() {
System.out.println("Fuji Apple is very costly.");
}
default void taste() {
System.out.println("Fuji Apple is very sweet.");
}
}
To enforce the Single Abstract method
, Java 8 provides an optional @FunctionalInterface
annotation to mark the Single Abstract Method Interface
or Functional Interfaces
. It will make sure the Interface
should not have more than 1 abstract
method or else it will throw a compilation
error.
@FunctionalInterface annotation is optional but recommended to use
package org.wesome.java8;
@FunctionalInterface
public interface Apple {
void show();
static void price() {
System.out.println("Fuji Apple is very costly.");
}
default void taste() {
System.out.println("Fuji Apple is very sweet.");
}
}
A normal Interface
can have an abstract
method, but an Interface
with @FunctionalInterface
annotation must have an abstract
method.
@FunctionalInterface
interface Apple extends Tree {
}
A Functional Interface
can extend other normal Interfaces
which may have default
and static
methods but should not have an abstract
method.
interface Tree {
static void fruit() {
System.out.println("i am tree, i give fruits.");
}
default void wood() {
System.out.println("i am tree, i give woods.");
}
}
@FunctionalInterface
interface Apple extends Tree {
void show();
}
A Functional Interface
cannot extend another Functional Interface
.
@FunctionalInterface
interface Tree {
void fruit();
}
@FunctionalInterface
interface Apple extends Tree {
void show();
}
Java built-in Function Interface
Java 8 allows developers to create Functional Interfaces
for Lambda Expression
, Java also provides java.util.function
package which has different types of pre-built-in Functional Interfaces
for most of the general purpose use cases.
- Consumer
The Java Consumer
interface defined in java.util.function.Consumer
. It takes the input parameter but doesn't return any value.
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
an example of a Consumer would be.
package org.wesome.java8;
import java.util.function.Consumer;
@FunctionalInterface
interface Tree<T> {
void show(T apple);
}
class Apple {
public static void main(String[] args) {
Tree<String> consumer = apple -> System.out.println(apple);
consumer.show("i love apple");
}
}
- Predicate
The Java Predicate
interface defined in java.util.function.Predicate
. It takes a single value as a parameter and returns a boolean (true or false) value.
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
an example of predicate would be
package org.wesome.java8;
import java.util.function.Consumer;
@FunctionalInterface
interface Tree<T> {
boolean checkForEmpty(T apple);
}
class Apple {
public static void main(String[] args) {
Tree<String> predicate = apple -> apple.isEmpty();
System.out.println(predicate.checkForEmpty("i love apple"));
}
}
- Function
The Java Function
interface defined in java.util.function.Function
. It takes a single parameter and returns a single value.
@FunctionalInterface
public interface Function<T,R> {
public <R> apply(T parameter);
}
an example of function
package org.wesome.java8;
import java.util.function.Consumer;
@FunctionalInterface
interface Tree<T, R> {
R countCharacters(T apple);
}
class Apple {
public static void main(String[] args) {
Tree<String, Integer> function = apple -> apple.length();
System.out.println(function.countCharacters("apple"));
}
}
- Supplier
The Java Supplier interface is defined in java.util.function.Supplier
. is a functional interface that supplies a value as a factory interface. it returns output without taking any input.
@FunctionalInterface
public interface Supplier<T> {
T get();
}
an example of a supplier
package org.wesome.java8;
import java.time.LocalDate;
import java.util.function.Consumer;
@FunctionalInterface
interface Tree<T> {
T today();
}
class Apple {
public static void main(String[] args) {
Tree<LocalDate> supplier = () -> LocalDate.now();
System.out.println("i ate apple on " + supplier.today());
}
}
Supplier
is majorly used as default value
of findFirst
or findAny
function.
package org.wesome.java8;
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;
class Apple {
public static void main(String[] args) {
Supplier<String> supplier = () -> "Fuji";
List<String> list = Arrays.asList("Jonagold", "Gala", "Macintosh");
String apple = list.stream().filter(app -> app.startsWith("F")).findFirst().orElseGet(supplier);
System.out.println("apple starts with F is " + apple);
}
}
The above first 3 functional interfaces have extensions or subinterfaces.
- Consumer -> Bi-Consumer
- Predicate -> Bi-Predicate
- Function -> Bi-Function, Unary Operator, Binary Operator