为什么Optional <t>被声明为最终类?</t>

时间:2014-03-29 17:56:16

标签: java java-8

我正在使用以下问题:Using Java 8's Optional with Stream::flatMap并希望向自定义Optional<T>添加方法,然后检查它是否有效。
更准确地说,我想在我的stream()中添加CustomOptional<T>,如果没有值,则返回空流;如果存在,则返回包含单个元素的流。

但是,我得出的结论是Optional<T>被宣布为最终版。

为什么会这样?有很多类未被声明为final,我个人认为这里没有理由声明Optional<T> final。

作为第二个问题,为什么不能将所有方法都归结为最终,如果担心它们会被覆盖,并且让课程不是最终的?

4 个答案:

答案 0 :(得分:15)

根据this page of the Java SE 8 API docsOptional<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类的所有用户都可以放心,他们收到的实例上的方法保持与他们总是返回相同值的契约。