Java Reference
In-Depth Information
Specifying a Method to Be Used Later
The final way to use method references is perhaps the strangest in Java's object-oriented world: you can
specify a method to be executed later on some arbitrary instance. The idea here is that you specify the name
of an instance method, and that becomes a function whose first argument is the one that is implemented.
So this:
UnaryOperator<String> stringOp = String::concat
Is equivalent to:
UnaryOperator<String> stringOp = (x,y) -> x.concat(y);
As you can see, the method reference is constructed exactly the same way as the static method. Java
recognizes it as an instance method, and therefore constructs the appropriate kind of lambda. Again, type
inference is doing a lot of heavy lifting for us in order to maintain a nice syntax.
This use of a method reference is very common as an alternative to iteration: you can pass in a method
that is executed for each element of a collection. Most developers familiar with this kind of stunt are used to
seeing it in dynamically typed languages: for instance, this is the “star-dot operator” in Groovy. In Java 8, you
can now pull off a similar stunt while retaining type safety.
Lambdas as Interface Implementations
If you are following along at home, you may have noticed the error when we attempted to assign a lambda
to an Object way back in Listing 2-3. That error read, “Target type of a lambda conversion must be an
interface.” That is some highly precise jargon, so let's unpack it. When the compiler encounters a lambda,
it attempts to make that lambda into a type that is sensical within Java's type system. That process is called
“lambda conversion,” and the destination for the lambda's conversion is called the “target type.” The
compiler only knows how to convert lambdas into interfaces—it cannot convert into primitive types, abstract
types, or concrete types. So far, we have been exclusively using Java's functional interfaces, but lambdas
can also be used to implement other interfaces, including interfaces that you define. This is very powerful,
especially when combined with the ability to make any method call into a lambda. We already saw this at
work in the previous chapter, in Listing 1-11 and 1-12. Here, we will get into the details and limitations.
The basic idea is that if you have an interface with a single abstract method, you can use a lambda
to provide an implementation of that interface. This means that it is easy to provide a lambda as an
implementation of Comparable , Iterable , and Autocloseable , but not Iterator or Collection . In Listing 2-23,
we see a few useful and common tricks.
Listing 2-23. Various Examples of Useful Interfaces Implemented by Lambdas
/**
* Given a {@link java.sql.Connection} in transactional mode, automatically
* commit a transaction using Java's {@code try-with-resources}.
*/
public static AutoCloseable autoCommit(Connection c) throws SQLException {
if (c == null) return () -> {};
return c::commit;
}
 
Search WWH ::




Custom Search