Java Reference
In-Depth Information
Listing 2-2. Identity Function Implemented Using an Anonymous Inner Class
public static <V> Function<V, V> identityFunctionAIC() {
return new Function<V, V>() {
@Override
public V apply(V value) {
return value;
}
};
}
Since Function is an interface, it is entirely possible to reimplement identityFunction() using an
anonymous inner class. The equivalent anonymous inner class implementation is given in Listing 2-2. If you
compare the two implementations, there are a few interesting things to note. First, the new format is much
more succinct. Second, the return found inside the anonymous inner class is implicit with the lambda:
the lambda is made up of a single statement, and so that statement's value is implicitly returned. Third, the
lambda version has no explicit declaration of value 's type: the compiler infers out the type of value based on
the context in which the value is used. This is a capability called “type inference,” and it is one of the nicest
things to come out of functional programming languages.
The type inference is why Listing 2-1 had to be wrapped in a method: you need to provide a way for the
compiler to know the argument and return type of the function. It is possible to assign a lambda directly
to a variable, but things get a bit tricky here: after all, what's the type? Truly old school Java developers
might be tempted to assign it to Object and circumvent the type of system completely, as in Listing 2-3. If
you do that, however, you will get a compiler error: the compiler needs to know what type you are trying to
implement. More modern Java developers would want to use generics to solve this purpose, as in Listing 2-4.
This will compile and work just fine. Unfortunately, that loses type information: the compiler no longer
knows the argument and return type are the same type. The method allows us to keep that information by
communicating all the type information that we have while remaining as generic as possible. If, however,
you knew that it was always going to be a Number , then you could define it as in Listing 2-5, and you'd get
all the succinct inline definition along with the type information. (The repetition of <Number,Number> in
Listing 2-5 is because both the argument and the return value are a Number: the first Number denotes the
argument's type, the second Number denotes the return value's type.) As a general rule, define lambdas
inline to the variable assignment if you know the concrete types, and define lambdas within methods
to capture more complex type information. Now that the Java compiler has type inference, that type
information is worth its weight in gold: don't lose it!
Listing 2-3. Identity Function Assigned to an Object Variable
// This code does not compile
Object funObject = it -> it;
Listing 2-4. Identity Function Assigned to a Generic Function Variable
Function<?,?> function = it -> it;
Listing 2-5. Identity Function for Number Instances Assigned to a Function Variable
Function<Number,Number> function = it -> it;
Search WWH ::




Custom Search