Using pattern instead of Optionals
Tagir Valeev
amaembo at gmail.com
Mon Oct 15 03:08:30 UTC 2018
Hello!
Just some thoughts. I recently revisited this Optional technetwork
article from Java 8 times:
https://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
In the article it's assumed that we need a code like this:
String version = "UNKNOWN";
if(computer != null){
Soundcard soundcard = computer.getSoundcard();
if(soundcard != null){
USB usb = soundcard.getUSB();
if(usb != null){
version = usb.getVersion();
}
}
}
Which is indeed ugly. Nowever changing the API methods getSoundcard()
and getUSB() to return Optionals (assuming that getVersion() never
returns null) and migrating local variable computer to Optional as
well we could write this:
String version = computer.flatMap(Computer::getSoundcard)
.flatMap(Soundcard::getUSB)
.map(USB::getVersion)
.orElse("UNKNOWN");
I personally not a big fan of changing everything to optionals (this
article even suggests to use optional fields!), because the resulting
functional code is much less flexible. Also not always you are in
position to update the existing API. Currently I often prefer
null-checks.
Currently you cannot express the original code with single expression
without some ugly static methods, unless you can afford to call
getters several times (and hope that they return stable result):
String version = computer != null && computer.getSoundcard() != null &&
computer.getSoundcard().getUSB() != null ?
computer.getSoundcard().getUSB().getVersion() : "UNKNOWN";
I realised that pattern matching allows you do to this:
String version = computer != null &&
computer.getSoundcard() instanceof Soundcard soundcard &&
soundcard.getUSB() instanceof USB usb ?
usb.getVersion() : "UNKNOWN";
Is such pattern usage considered idiomatic? Could it be simplified?
I'm not sure that `instanceof var soundcard` could be used here,
because it seems that `var` would match null as well. Well, assuming
that computer can be deconstructed into Soundcard which can be
deconstructed into USB, we could write even simpler:
String version = computer instanceof Computer(Soundcard(USB usb)) ?
usb.getVersion() : "UNKNOWN";
However this looks like an abuse of deconstruction: unlikely one have
a constructor which creates a Computer from Soundcard only. Or
probably we can create static named deconstructors like this (I saw
something like this in some documents):
String version = computer instanceof
Computer.withSoundcard(Soundcard.withUSB(var usb)) ?
usb.getVersion() : "UNKNOWN";
Will this be possible?
With best regards,
Tagir Valeev.
More information about the amber-spec-experts
mailing list