Java Reference
In-Depth Information
try {
return Files.lines(file).iterator();
} catch (IOException ioe) {
throw new UncheckedIOException(
"Error reading lines from " + file, ioe);
}
}
);
}
}
The key thing to recognize from Listing 7-13 is that we delegate our abstract method implementation
to a lambda. That lambda is passed into the constructor. That is the basic pattern for using lambdas to
implement abstract methods. You may be tempted to accept multiple lambdas into a constructor, and
thereby to implement more and more abstract elements. Don't do this for two reasons: first, because it
encourages people to create ad hoc classes when they should have reusable classes; second, because it is
hard to read, and Java already has an inline class definition format that works well for this case. That is one
particular case where lambdas make things less readable, not more.
The Transparent Optional Trick
There is one last very useful trick for working with legacy code. This trick is a way to deal with null values.
When Java encounters a null value, it throws the obnoxiously omnipresent NullPointerException .
The message for the NullPointerException looks like this:
Exception in thread "main" java.lang.NullPointerException
As a Java developer with practically any experience understands, that is a totally unhelpful message.
For one thing, it's not even clear what is null, so it could be anything on that line that caused the problem.
There is also no state of the application that is communicated in that error message. This message is of
extremely limited utility, and it is part of the reason why null should be driven entirely from your codebase
as quickly as possible. Now that we have Optional , there is absolutely no need for null.
Of course, legacy code did not have Optional , and the legacy developers may not have been so
enlightened as we now are. However, we can be rid of the null values and provide more useful error
messaging at the same time in a transparent way. The trick is to use an optional value internally, while
providing a (mostly) consistent API externally. The requirement for the consistent API is that we throw a
NullPointerException if the value is null, which we can do using the Optional.orElseThrow(Supplier<E
xception>) method. Additionally, we provide a way to get the value as an Optional, so people who really do
want to check whether or not the value exists can do so that way. The intent would be that the code would
eventually migrate over to the accessors acting directly on the Optional type instead, so we can deprecate
the old setter. As a syntactic convenience, it is nice to leave a setter that directly sets the value via
Optional.ofNullable(Object) : if you provide that overload of the setter, then the caller doesn't have
to do their own wrapping of the raw value. An example of this implementation is given in Listing 7-14.
 
Search WWH ::




Custom Search