Define and write functional interfaces and describe the interfaces of the java.util.function package.
Functional interfaces are a new type of Java Interface. In this section the concepts will be presented and in the Lambda Expressions section you will see how to use them.
-
Functional Interfaces are those that have only one abstract method, called the "functional method".
-
The use of the
@FunctionalInterface
annotation is recommended, but not required.src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_Basic.javalink:../../../src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_Basic.java[role=include]
The
@FunctionalInterface
annotation ensures at compile time that this interface is functional. It also indicates to other developers that it was created for use in lambda expressions, so you should not create other abstract methods within it. -
Additional methods that are
default
orstatic
don’t make the interface to be functional.src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_DefaultStatic.javalink:../../../src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_DefaultStatic.java[role=include]
Remember that
static
methods on interfaces can be called directly, such asExecutable.execute (…)
. Thus, there is no interference in the fact that the interface is functional.On the other hand,
default
methods can only be called if you have an instance of the interface, but they already have a default implementation.If you have questions about
static
ordefault
in interfaces, go back to the "Static and default methods of an interface" section. -
Overriding a public method of
java.lang.Object
in the interface doesn’t turn it to a no functional interface.src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_OverrideObject.javalink:../../../src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_OverrideObject.java[role=include]
-
An interface that extends another without adding abstract methods can also be functional.
src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_Extends.javalink:../../../src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_Extends.java[role=include]
-
If one interface extends another that is functional but adds new abstract methods, it is not functional.
src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_ExtendsNewMethod.javalink:../../../src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_ExtendsNewMethod.java[role=include]
-
Using the
@FunctionalInterface
annotation on interfaces that have more than one abstract method causes a compilation error.src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_InterfaceCompilationError.javalink:../../../src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_InterfaceCompilationError.java[role=include]
-
Using the
@FunctionalInterface
annotation on any type other than an interface causes a compilation error.src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_ClassCompilationError.javalink:../../../src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_ClassCompilationError.java[role=include]
-
Functional methods can have any return.
src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_ReturnType.javalink:../../../src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_ReturnType.java[role=include]
-
Functional interfaces are meant to be used in lambda expressions, but the code will also compile normally if a class implements it.
src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_Implement.javalink:../../../src/org/j6toj8/lambda/functionalinterfaces/FunctionalInterfaces_Implement.java[role=include]
This is just an example for you to know that this implementation does not generate compilation errors, but does not use functional interfaces in this way. In the Lambda Expressions section, you will see how functional interfaces should be used in practice.
The interfaces described here are available in the java.util.function
package. This section will present only its definitions, as there is later a specific section to deal with the examples of each.
There are other interfaces in this package besides those listed here, but they are only specific to dealing with primitive types, following the same definitions.
-
Supplier<T>
: Represents a results provider.A
Supplier
literally only provides data or results to someone. A sequential number generator, for example, may be aSupplier
. -
Consumer<T>
: Represents an operation that accepts a single entry and has no return. -
BiConsumer<T, U>
: Represents an operation that accepts two inputs and has no return.Consumers
are pretty much the opposite ofSupplier
, as they only receive data or information and treat them in some way. -
Function<T, R>
: Represents a function that accepts an argument and produces a return. -
BiFunction<T, U, R>
: Represents a function that takes two arguments and produces a return.The
Function
are more similar to the functions we already know. They receive data and produce a return. -
Predicate<T>
: Represents a proposition (Boolean value function) of an argument. -
BiPredicate<T, U>
: Represents a proposition (Boolean value function) of two arguments.Predicate
is similar toFunction
, but always returns a Boolean result, so it is used for true or false "tests". -
UnaryOperator<T>
: Represents an operation on a single operator that produces a result of the same type as it. -
BinaryOperator<T>
: Represents an operation on two operators that produces a result of the same type as them.The
Operator
areFunction
specializations, because although they also always receive and produce results, the inputs and outputs are always the same type.
-
Introducing Functional Programming
Boyarsky, Jeanne; Selikoff, Scott. OCP: Oracle Certified Professional Java SE 8 Programmer II Study Guide (p. 52). Wiley. Kindle Edition.
-
Annotation Type FunctionalInterface. Java Plataform SE 8.
-
Package java.util.function. Java Plataform SE 8.
-
Lambda Expressions. The Java™ Tutorials.