Java Reference
In-Depth Information
) {
Objects.requireNonNull(exceptionHandler,
"exception handler for I/O exceptions");
Objects.requireNonNull(consumer,
"consumer to apply to temp file");
Function<IOException, Optional<Object>> exceptionFunction =
functionise(exceptionHandler);
Function<File, Optional<Object>> consumerFunction = functionise(consumer);
withTempFile(exceptionFunction, consumerFunction);
}
With all this functional niceness in place, we should really finish with an API that will feel natural to
the Java traditionalists. This would mean that a function that takes a consumer, and throws an exception
if an IOException occurs. In this case, we will create a container for the exception. The exception handler
will store the exception into the consumer. When the method returns, we can check to see if the container is
set, and throw the exception if it is. We need the container because variables used in lambdas are implicitly
final , which means that we cannot set a variable that is defined outside of the lambda. This implementation
will actually use null , because Optional is immutable, and other options (such as using a List ) are more
obscuring than clear. The code is given in Listing 4-6.
Listing 4-6. Method Accepting a Consumer to Process a Temporary File, and Throwing an Exception
on Error
/**
* Creates a temporary file, passes it into the given consumer, and
* deletes the temporary file when the function is complete.
*
* @param consumer The consumer to call with the temporary file, and
* it is never {@code null}; may not be {@code null}.
* @throws java.io.IOException If an exception occurs.
*/
public static void withTempFile(Consumer<File> consumer) throws IOException {
AtomicReference<IOException> reference = new AtomicReference<>(null);
Consumer<IOException> exceptionHandler = reference::set;
withTempFile(exceptionHandler, consumer);
if (reference.get() != null) throw reference.get();
}
Listing 4-6 is also an excellent example about why you shouldn't release Zalgo. (See the “Don't
Release Zalgo” in chapter 2.) The withTempFile method guarantees that if it will execute its argument,
then that argument will be executed before the method returns. Because of that, we know that the
if(reference.get() != null) line will execute after the exceptionHandler implementation executes.
If the exceptionHandler sometimes executed later, then our code would break under some uncertain
(undoubtedly surprising and unfortunate) circumstances.
Reading All the Lines of Files in a Directory
Now that we have exercised our real-world lambda skills, it is time to take on something more involved. For our
next goal, we will print out all the lines of the files in a directory. This will give us a chance to decompose a more
complex problem, and to see how to combine streams. By the time we are done with this exercise, you should
have a good sense for how streams can be manipulated, both while working with I/O and more generally.
 
Search WWH ::




Custom Search