What's the point of Guava's Optional class

JavaGenericsGuava

Java Problem Overview


I've recently read about this and seen people using this class, but in pretty much all cases, using null would've worked as well - if not more intuitively. Can someone provide a concrete example where Optional would achieve something that null couldn't or in a much cleaner way? The only thing I can think of is to use it with Maps that don't accept null keys, but even that could be done with a side "mapping" of null's value. Can anyone provide me with a more convincing argument?

Java Solutions


Solution 1 - Java

Guava team member here.

Probably the single biggest disadvantage of null is that it's not obvious what it should mean in any given context: it doesn't have an illustrative name. It's not always obvious that null means "no value for this parameter" -- heck, as a return value, sometimes it means "error", or even "success" (!!), or simply "the correct answer is nothing". Optional is frequently the concept you actually mean when you make a variable nullable, but not always. When it isn't, we recommend that you write your own class, similar to Optional but with a different naming scheme, to make clear what you actually mean.

But I would say the biggest advantage of Optional isn't in readability: the advantage is its idiot-proof-ness. It forces you to actively think about the absent case if you want your program to compile at all, since you have to actively unwrap the Optional and address that case. Null makes it disturbingly easy to simply forget things, and though FindBugs helps, I don't think it addresses the issue nearly as well. This is especially relevant when you're returning values that may or may not be "present." You (and others) are far more likely to forget that other.method(a, b) could return a null value than you're likely to forget that a could be null when you're implementing other.method. Returning Optional makes it impossible for callers to forget that case, since they have to unwrap the object themselves.

For these reasons, we recommend that you use Optional as a return type for your methods, but not necessarily in your method arguments.

(This is totally cribbed, by the way, from the discussion here.)

Solution 2 - Java

It really looks like the Maybe Monad pattern from Haskell.

You should read the following, Wikipedia Monad (functional programming):

And read From Optional to Monad with Guava on Kerflyn's Blog, which discusses about the Optional of Guava used as a Monad:


Edit: With Java8, there's a built-in Optional that has monadic operators like flatMap. This has been a controversial subject but finally has been implemented.

See http://www.nurkiewicz.com/2013/08/optional-in-java-8-cheat-sheet.html

public Optional<String> tryFindSimilar(String s)  //...

Optional<Optional<String>> bad = opt.map(this::tryFindSimilar);
Optional<String> similar =       opt.flatMap(this::tryFindSimilar);

The flatMap operator is essential to allow monadic operations, and permits to easily chain calls that all return Optional results.

Think about it, if you used the map operator 5 times you would end up with an Optional<Optional<Optional<Optional<Optional<String>>>>>, while using flatMap would give you Optional<String>

Since Java8 I would rather not use Guava's Optional which is less powerful.

Solution 3 - Java

One good reason to use it is that it makes your nulls very meaningful. Instead of returning a null that could mean many things (like error, or failure, or empty,etc) you can put a 'name' to your null. Look at this example:

lets define a basic POJO:

class PersonDetails {

String person;
String comments;

public PersonDetails(String person, String comments) {
    this.person = person;
    this.comments = comments;
}

public String getPerson() {
    return person;
}


public String getComments() {
    return comments;
}

}

Now lets make use of this simple POJO:

public Optional<PersonDetails> getPersonDetailstWithOptional () {

  PersonDetails details = null; /*details of the person are empty but to the caller this is meaningless,
  lets make the return value more meaningful*/
  

    if (details == null) {
      //return an absent here, caller can check for absent to signify details are not present
        return Optional.absent();
    } else {
      //else return the details wrapped in a guava 'optional'
        return Optional.of(details);   
    }
}

Now lets avoid using null and do our checks with Optional so its meaningful

public void checkUsingOptional () {

    Optional<PersonDetails> details = getPersonDetailstWithOptional();
    
    /*below condition checks if persons details are present (notice we dont check if person details are null,
    we use something more meaningful. Guava optional forces this with the implementation)*/
    if (details.isPresent()) {

      PersonDetails details = details.get();
        
        // proceed with further processing
        logger.info(details);
        
    } else {
        // do nothing
        logger.info("object was null"); 
    }
    
    assertFalse(details.isPresent());
}

thus in the end its a way to make nulls meaningful, & less ambiguity.

Solution 4 - Java

The most important advantage of Optional is that it adds more details to the contract between the implementer and caller of a function. For this reason is both useful for parameters and return type.

If you make the convention to always have Optional for possible null objects you add more clarifications to cases like:

  1. Optional<Integer> maxPrime(Optional<Integer> from, Optional<Integer> to)

    The contract here clearly specifies that there is a chance that a result is not returned but also shows that it will work with from and to as absent.

  2. Optional<Integer> maxPrime(Optional<Integer> from, Integer to)

    The contract specifies that the from is optional so an absent value might have a special meaning like start from 2. I can expect that a null value for the to parameter will throw an exception.

So the good part of using Optional is that the contract became both descriptive (similar with @NotNull annotation) but also formal since you must write code .get() to cope with Optional.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRAYView Question on Stackoverflow
Solution 1 - JavaLouis WassermanView Answer on Stackoverflow
Solution 2 - JavaSebastien LorberView Answer on Stackoverflow
Solution 3 - Javaj2emanueView Answer on Stackoverflow
Solution 4 - JavaraisercostinView Answer on Stackoverflow