A functional interface is an interface with one method and used as the type of a lambda expression.
public interface ActionListener extends EventListener { public void actionPerformed(ActionEvent event); }
ActionListener
has only one method, actionPerformed
.
It is a functional interface.
It doesn't matter what the single method is called,
the Java compiler will match it up to your lambda expression
as long as it has a compatible method signature.
A lambda expression represents an instance of a functional interface.
The type of a lambda expression is a functional interface type.
(String str) -> str.length()
takes a
String parameter and returns its length.
Its type can be any functional interface type with an abstract method that takes a String as a parameter and returns an int.
The following is an example of such a functional interface:
@FunctionalInterface interface Processor { int getStringLength(String str); }
We can assign lambda expression to its functional interface instance.
Processor stringProcessor = (String str) -> str.length();
In the following code we assign a lambda expression to its functional interface. Then we execute the lambda expression by calling the method defined in the functional interface and pass in a parameter.
public class Main { public static void main(String[] argv) { Processor stringProcessor = (String str) -> str.length(); String name = "Java Lambda"; int length = stringProcessor.getStringLength(name); System.out.println(length);/* ww w . j a va 2 s .co m*/ } } @FunctionalInterface interface Processor { int getStringLength(String str); }
The code above generates the following result.
A lambda expression by itself cannot be used as a standalone expression.
The type of a lambda expression is inferred by the compiler.
A functional interface is an interface that has one abstract method.
We cannot use the following types of methods to declare a functional interface:
A functional interface can redeclare the methods in the Object class. And that method is not counted as abstract method. Therefore we can declare another method used by lambda expression.
Consider the Comparator class in the java.util
package, as shown:
package java.util; // w w w. j a v a 2 s . co m @FunctionalInterface public interface Comparator<T> { // An abstract method declared in the functional interface int compare(T o1, T o2); // Re-declaration of the equals() method in the Object class boolean equals(Object obj); ... }
The Comparator interface has two abstract methods: compare()
and equals()
.
The equals()
method is a redeclaration of the equals()
method from the Object class.
@FunctionalInterface
annotation is defined in the java.lang package.
We can optionally use it to mark a functional interface.
If the annotation @FunctionalInterface
is annotated on a non-functional interface
or other types such as classes, a compile-time error occurs.
An interface with one abstract method is still a functional interface even we don't
annotated it with @FunctionalInterface
.
public class Main { public static void main(String[] argv) { Processor stringProcessor = (String str) -> str.length(); String name = "Java Lambda"; int length = stringProcessor.getStringLength(name); System.out.println(length);/* w w w.j ava 2 s. c o m*/ } } @FunctionalInterface interface Processor { int getStringLength(String str); }
The code above generates the following result.
We can use type parameters with a functional interface to create generic functional interface.
The following code creates a generic functional parameter function interface with one type parameter T.
@FunctionalInterface public interface Comparator<T> { int compare(T o1, T o2); }
The following code defines a non-generic functional interface with an abstract generic method:
@FunctionalInterface public interface Processor { <T> void process(T[] list); }
Java 8 has functional interfaces in the package java.util.function.
To
represent a function that takes an argument
of type T
and returns a result of type R
.
public interface Function<T,R>{ ... public R apply(T t); ... }
To represent a function that takes two arguments of types T and U, and returns a result of type R.
public interface BiFunction<T,U,R>{ ... public R apply(T t, U u); ... }
To represent a boolean function that returns true
or false
for the specified argument.
public Predicate<T> { ... public boolean test(T t); ... }
To represent a boolean function that returns true
or false
for the two specified arguments.
public interface BiPredicate<T,U>{ ... public boolean test(T t, U u); ... }
To represent an operation that takes an argument and returns no result.
public interface Consumer<T>{ ... public void accept(T t); ... }
To represent an operation that takes two arguments and returns no result.
public interface BiConsumer<T,U>{ ... public void accept(T t, U u); ... }
To represent a function that returns a value as of type T.
public interface Supplier<T>{ ... public T get(); ... }
To represent a function that takes an argument and returns a result of the same type.
public interface UnaryOperator<T>{ ... public T apply(T t); ... }
To represent a function that takes two arguments and returns a result of the same type.
public interface BinaryOperator<T>{ ... public T apply(T t1, T t2); ... }
The above generic buildin functional interfaces are all the generic versions of more specialized functional interfaces.
For example, IntConsumer
is a specialized version of Consumer<T>
.