Java Reference
In-Depth Information
Unfortunately, this plays poorly with the syntax of lambdas. The try-with-resources block is not a single
statement, so if you want your try-with-resources as a body of a lambda, you immediately have to wrap that
call in a pair of brackets, such as this:
Consumer<Object> consumer = it -> {
try (InputStream in = acquireInputStream()) {
// Do something
} catch (IOException exception) {
// Handle exception, which may include close exceptions
}
};
Note also that we have to put the lambda within the try-with-resources block itself, or we have to
execute the lambda before we exit the try-with-resources block. If you assign the lambda within the try-with-
resources block, exit the try-with-resources block, and then try to call the lambda, the input stream will be
closed. The order of operations will be as follows:
1.
Enter try-with-resources block.
2.
Assign the lambda.
3.
Exit try-with-resources block, closing the input stream.
4.
Call the lambda.
A demonstration of this error is in Listing 7-1. When you walk through it in this way, the error seems
obvious. However, this is an easy mistake to make, and it can be quite tricky to detect in practice. It can be
especially tricky to detect if you are calling into code that releases Zalgo. If you remember from chapter 2,
a developer “releases Zalgo” any time calling code sometimes executes immediately and sometimes
executes in a deferred manner. If your code releases Zalgo, then you might pass your resource into that code
expecting it to be executed immediately. However, when it executes in that deferred manner, you will have
a race condition: the try-with-resource block will call at some point in the future, and the calling code will
read the input stream at some other point in the future. Which one comes first is at the capricious whim of
the thread scheduler. The result will be intermittent closed input streams: you will get exceptions when the
reading code occasionally loses the race.
Listing 7-1. Calling a Lambda after Its Resources Are Closed
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.util.function.*;
public class Listing1 {
public static void main(String[] args) {
Consumer<Object> consumer = null;
try (InputStream in = acquireInputStream()) {
consumer = it -> {
try {
System.out.println("Trying to read!");
in.read();
} catch (IOException ioe) {
 
Search WWH ::




Custom Search