【发布时间】:2018-01-13 04:52:32
【问题描述】:
在 Java 中,Optional 实现为public final class Optional<T> { ... },而不是Some 和None 的密封层次结构。
为什么这里不是这样?这是Java中缺少sealed的解决方法吗?有没有更深层次的道理?
如果您查看方法实现,您会发现通过这种方式,它具有丑陋的空检查:
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));
}
}
它们不仅丑陋,而且如果您有更长的方法链,则需要在每次调用期间评估 isPresent,即使 Optional 从一开始就为空。
如果我们可以将一个固定的实现向下传递,它就可以避免。
optional
.map(i -> i) // isPresent()
.map(Object::toString) // isPresent()
.map(String::length) // isPresent()
.map(...) // isPresent()
问题
为什么不使用子类型来模拟空和非空案例?
我并没有特别问为什么 Optional 是最终的,而是为什么它没有像许多其他语言那样用 Some 和 None 实现,所以 Why is optional declared as a final class 是不是很有帮助。
【问题讨论】:
-
如果 jsr 没有说明这件事,我们只能推测。
-
@VinceEmigh 我不是在问禁止继承。我想知道是什么推动了在不使用任何形式的继承的情况下实现 Optional 的原因——这是 Scala、Haskell 甚至 Java 的 Vavr 库中的标准方法。
-
这不是没有密封的解决方法。构造函数很可能是私有的,并且 Some 和 None 实现为私有静态嵌套类。我猜使用 if 的实现比基于多态的实现更简单、更快。
-
@JBNizet 这并不能真正说服我。通过这种方式,如果您有 N 个链式 map() 调用,它将评估
isPresentN 次,这可以通过采用 Some/None 方式来避免。 -
Spec for value-based types。 A paper on value-types(计划为 Valhalla)“值可以参与基于继承的子类型化吗?不能。” - “限制或禁止值类型的子类化和子类型化的决定是必要的以避免指针多态。" - 似乎他们只是在坚持他们的计划,可能是将现有的基于值的类转换为值类型。