Why is Java 8 Optional implemented as final, without Some and None hierarchy?

Viewed 1968

In Java, Optional is implemented as public final class Optional<T> { ... } and not as a sealed hierarchy of Some and None.

Why is this not the case here? Is this a workaround for the absence of sealed in Java? Is there any deeper reasoning behind it?

If you have a look at method implementations, you will see that by going this way cases it features ugly null checks:

public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent())
        return empty();
    else {
        return Optional.ofNullable(mapper.apply(value));
    }
}

They're not only ugly but if you have a longer method chain, isPresent will need to be evaluated during every call, even if the Optional is empty since the beginning.

If we could pass a fixed implementation down the chain, it could be avoided.

optional
  .map(i -> i) // isPresent()
  .map(Object::toString) // isPresent()
  .map(String::length) // isPresent()
  .map(...) // isPresent()

Question

Why weren't subtypes used to model empty and non-empty cases?


I'm not specifically asking why Optional is final, rather why it wasn't implemented with Some and None, as many other languages do, so Why is optional declared as a final class is not really helpful.

2 Answers
Related