Java Reference
In-Depth Information
File file = null;
try {
file = File.createTempFile("funfile", "tmp");
return function.apply(file);
} catch(IOException ioe) {
exceptionHandler.consume(ioe);
} finally {
if(file == null) file.delete();
}
}
// This is not valid Java code: read on!
There are three problems with this code. One problem is that it uses
null
for the file, when
null
is
not a valid value. Another is a problem with the logic of this code. The last problem is an API problem. The
compiler would catch the second problem. The first problem should be caught by your newfound sensibility,
where reading
null
in code is like hearing nails on a chalkboard. The third problem is by far the subtlest, and
will only be caught once you have experience manipulating methods as lambdas.
The first problem is the fact that we are using
null
. Starting in Java 8, you should only use
null
if
you want to get a
NullPointerException
. In all other cases when you would use
null
, you should use
the
Optional
class instead. The
Optional
class is the implementation of the “option” or “maybe” pattern
common in functional programming, and it is how functional languages avoid even having a concept of
null
or any equivalent to the
NullPointerException
. The
Optional
class is a container that holds up to one
single element, and provides convenient ways to act on the contained element if it exists. If we rewrite the
code using
Optional
, we eliminate the possibility of a
NullPointerException
and get more readable code.
It looks like this:
<RETURN_T> RETURN_T withTempFile(
Function<FunFile, RETURN_T> function,
Consumer<IOException> exceptionHandler
) {
Optional<File> file = Optional.empty();
try {
file = Optional.of(File.createTempFile("funfile", "tmp"));
return file.map(function).get();
} catch(IOException ioe) {
exceptionHandler.consume(ioe);
} finally {
file.ifPresent(File::delete);
}
}
// This is still not valid Java code: read on!
This code still won't compile, however, which brings us to our second problem. The second problem in
our code is that we do not have a return value in the case of the exception handler. If you get into the
catch
block, and you execute the consumer, then what is there return value of the method? An old-school Java