Function Interface in Java with Example

preview_player
Показать описание


T: denotes the type of the input argument
R: denotes the return type of the function

Functional interfaces provide target types for lambda expressions and method references.

Java 8 brought a powerful new syntactic improvement in the form of lambda expressions. A lambda is an anonymous function that we can handle as a first-class language citizen. For instance, we can pass it to or return it from a method.

Before Java 8, we would usually create a class for every case where we needed to encapsulate a single piece of functionality. This implied a lot of unnecessary boilerplate code to define something that served as a primitive function representation.

Java 8 brought a powerful new syntactic improvement in the form of lambda expressions. A lambda is an anonymous function that we can handle as a first-class language citizen. For instance, we can pass it to or return it from a method.

Before Java 8, we would usually create a class for every case where we needed to encapsulate a single piece of functionality. This implied a lot of unnecessary boilerplate code to define something that served as a primitive function representation.

It's recommended that all functional interfaces have an informative @FunctionalInterface annotation. This clearly communicates the purpose of the interface, and also allows a compiler to generate an error if the annotated interface does not satisfy the conditions.

Any interface with a SAM(Single Abstract Method) is a functional interface, and its implementation may be treated as lambda expressions.

Note that Java 8's default methods are not abstract and do not count; a functional interface may still have multiple default methods. We can observe this by looking at the Function's documentation.

The most simple and general case of a lambda is a functional interface with a method that receives one value and returns another. This function of a single argument is represented by the Function interface, which is parameterized by the types of its argument and a return value:

In this case, we will calculate a value by applying a function to a key, put inside a map, and also returned from a method call. We may replace the lambda with a method reference that matches passed and returned value types.

Remember that an object we invoke the method on is, in fact, the implicit first argument of a method. This allows us to cast an instance method length reference to a Function interface:

The Function interface also has a default compose method that allows us to combine several functions into one and execute them sequentially:

The quoteIntToString function is a combination of the quote function applied to a result of the intToString function.

Since a primitive type can’t be a generic type argument, there are versions of the Function interface for the most used primitive types double, int, long, and their combinations in argument and return types:

IntFunction, LongFunction, DoubleFunction: arguments are of specified type, return type is parameterized
ToIntFunction, ToLongFunction, ToDoubleFunction: return type is of specified type, arguments are parameterized
DoubleToIntFunction, DoubleToLongFunction, IntToDoubleFunction, IntToLongFunction, LongToIntFunction, LongToDoubleFunction: having both argument and return type defined as primitive types, as specified by their names
As an example, there is no out-of-the-box functional interface for a function that takes a short and returns a byte, but nothing stops us from writing our own.

To define lambdas with two arguments, we have to use additional interfaces that contain “Bi” keyword in their names: BiFunction, ToDoubleBiFunction, ToIntBiFunction, and ToLongBiFunction.
Рекомендации по теме