Java Reference
In-Depth Information
Logger logger
=
new
new
Logger
();
iif
(
logger
.
isDebugEnabled
()) {
logger
.
debug
(
"Look at this: "
+
expensiveOperation
());
}
What we actually want to be able to do is pass in a lambda expression that generates a
String
to be used as the message. This expression would be called only if the
Logger
was
actually at debug level or above. This approach would allow us to rewrite the previous code
example to look like the code in
Example 4-2
.
Example 4-2. Using lambda expressions to simplify logging code
Logger logger
=
new
new
Logger
();
logger
.
debug
(() ->
"Look at this: "
+
expensiveOperation
());
So how do we implement this method from within our
Logger
class? From the library point
of view, we can just use the builtin
Supplier
functional interface, which has a single
get
method. We can then call
isDebugEnabled
in order to find out whether to call this method
and pass the result into our
debug
method if it is enabled. The resulting code is shown in
Example 4-3. The implementation of a lambda-enabled logger
public
public
void
void
debug
(
Supplier
<
String
>
message
) {
iif
(
isDebugEnabled
()) {
debug
(
message
.
get
());
}
}
Calling the
get()
method in this example corresponds to calling the lambda expression that
was passed into the method to be called. This approach also conveniently works with an-
onymous inner classes, which allows you maintain a backward-compatible API if you have
consumers of your code who can't upgrade to Java 8 yet.
It's important to remember that each of the different functional interfaces can have a different
name for its actual method. So, if we were using a
Predicate
, we would have to call
test
,
or if we were using
Function
, we would have to call
apply
.
Primitives
You might have noticed in the previous section that we skimmed over the use of
primitive
types. In Java we have a set of parallel types—for example,
int
and
Integer
—where one is