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.