Skip to content

Instantly share code, notes, and snippets.

@cchacin
Created October 29, 2016 08:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cchacin/0d03e89c34a54a5ca38f4ee75e42ae4d to your computer and use it in GitHub Desktop.
Save cchacin/0d03e89c34a54a5ca38f4ee75e42ae4d to your computer and use it in GitHub Desktop.
Optionals vs. Nulls

Optionals vs. Nulls

Given a computer object get the USB version of the computer's soundcard, and if it's null return UNKNOWN

Java 7 traditional approach

class Computer {
    private final Soundcard soundcard;

    Computer(final Soundcard soundcard) {
        this.soundcard = soundcard;
    }

    Soundcard getSoundcard() {
        return this.soundcard;
    }
}
class Soundcard {
    private final USB usb;

    Soundcard(final USB usb) {
        this.usb = usb;
    }

    USB getUsb() {
        return this.usb;
    }
}
class USB {
    private final String version;

    USB(final String version) {
        this.version = version;
    }

    public String getVersion() {
        return this.version;
    }
}
// Horrible idea => NPE
public String getVersionWithNullsUnsafe() {
    return Computer
            .buildSampleComputer()
            .getSoundcard()
            .getUsb()
            .getVersion();
}
// Better huh? => not really
public String getVersionWithNulls() {
    String version = "UNKNOWN";
    final Computer computer = Computer.buildSampleComputer();
    if (computer != null) {
        final Soundcard soundcard = computer.getSoundcard();
        if (soundcard != null) {
            final USB usb = soundcard.getUsb();
            if (usb != null) {
                version = usb.getVersion();
            }
        }
    }
    return version;
}

Java 8 Optional approach

class Computer {
    private final Soundcard soundcard;

    Computer(final Soundcard soundcard) {
        this.soundcard = soundcard;
    }

    Optional<Soundcard> getSoundcard() { // returning opional instead
        return Optional.ofNullable(this.soundcard);
    }

    static Optional<Computer> buildSampleComputer() { // returning opional instead
        return Optional.of(new Computer(
                        new Soundcard(
                                new USB("1.2")
                        )
                )
        );
    }
}
class Soundcard {
    private final USB usb;

    Soundcard(final USB usb) {
        this.usb = usb;
    }

    Optional<USB> getUsb() { // returning opional instead
        return Optional.ofNullable(this.usb);
    }
}
class USB {
    private final String version;

    USB(final String version) {
        this.version = version;
    }

    public String getVersion() {
        return this.version;
    }
}
// this is fluent
// more elegant
// no side effects
// no mutability
// easy to read
public String getVersion() {
    return Computer.buildSampleComputer()
            .flatMap(Computer::getSoundcard)
            .flatMap(Soundcard::getUsb)
            .map(USB::getVersion)
            .orElse("UNKNOWN");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment