我正在使用以下问题:Using Java 8's Optional with Stream::flatMap并希望向自定义Optional<T>
添加方法,然后检查它是否有效。
更准确地说,我想在我的stream()
中添加CustomOptional<T>
,如果没有值,则返回空流;如果存在,则返回包含单个元素的流。
但是,我得出的结论是Optional<T>
被宣布为最终版。
为什么会这样?有很多类未被声明为final,我个人认为这里没有理由声明Optional<T>
final。
作为第二个问题,为什么不能将所有方法都归结为最终,如果担心它们会被覆盖,并且让课程不是最终的?
答案 0 :(得分:15)
根据this page of the Java SE 8 API docs,Optional<T>
是基于值的类。根据{{3}},基于值的类必须是不可变的。
将Optional<T>
中的所有方法声明为final将阻止覆盖这些方法,但这不会阻止扩展类添加字段和方法。扩展类并添加字段以及更改该字段值的方法将使该子类可变,从而允许创建可变Optional<T>
。以下是如果Optional<T>
未被声明为final的话,可以创建的这样一个子类的示例。
//Example created by @assylias
public class Sub<T> extends Optional<T> {
private T t;
public void set(T t) {
this.t = t;
}
}
声明Optional<T>
final会阻止创建类似上面的子类,从而保证Optional<T>
始终是不可变的。
答案 1 :(得分:2)
正如其他人所说,Optional是一个基于值的类,因为它是一个基于值的类,所以它应该是不可变的,需要它是最终的。
但我们错过了这一点。基于值的类是不可变的主要原因之一是保证线程安全性。使其不可变使其线程安全。比如String或原始包装器,如Integer或Float。由于类似的原因,他们被宣布为最终决定。
答案 2 :(得分:1)
尽管我们不能扩展Optional类,但是我们可以创建自己的包装器类。
public final class Opt {
private Opt() {
}
public static final <T> Stream<T> filledOrEmpty(T t) {
return Optional.ofNullable(t).isPresent() ? Stream.of(t) : Stream.empty();
}
}
希望对您有帮助。很高兴看到反应!
答案 3 :(得分:0)
可能原因与String
最终的原因相同;也就是说,Optional
类的所有用户都可以放心,他们收到的实例上的方法保持与他们总是返回相同值的契约。