Java 为什么是可选的<;T>;声明为最终类?

Java 为什么是可选的<;T>;声明为最终类?,java,java-8,Java,Java 8,我在玩下面的问题:想给自定义的可选方法添加一个方法,然后检查它是否有效。 更准确地说,我想在我的CustomOptional中添加一个stream(),如果不存在值,则返回一个空流;如果存在,则返回一个包含单个元素的流 然而,我得出的结论是,Optional被声明为final 为什么会这样?有很多类没有声明为final,我个人认为这里没有理由声明Optionalfinal 第二个问题是,如果担心所有方法都会被重写,并使类成为非final类,为什么不能使所有方法都是final 原因可能与Strin

我在玩下面的问题:想给自定义的
可选方法添加一个方法,然后检查它是否有效。
更准确地说,我想在我的
CustomOptional
中添加一个
stream()
,如果不存在值,则返回一个空流;如果存在,则返回一个包含单个元素的流

然而,我得出的结论是,
Optional
被声明为final

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


第二个问题是,如果担心所有方法都会被重写,并使类成为非final类,为什么不能使所有方法都是final

原因可能与
String
为final的原因相同;也就是说,
Optional
类的所有用户都可以确保他们接收到的实例上的方法遵守始终返回相同值的约定。

根据,
Optional
是一个基于值的类。根据,基于值的类必须是不可变的

Optional
中的所有方法声明为final将防止重写这些方法,但这不会阻止扩展类添加字段和方法。扩展该类并添加一个字段以及一个更改该字段值的方法将使该子类可变,从而允许创建可变的
可选的
。下面是这样一个子类的示例,如果
Optional
未声明为final,则可以创建该子类

//Example created by @assylias
public class Sub<T> extends Optional<T> {
    private T t;

    public void set(T t) {
        this.t = t;
    }
}
//由@assylias创建的示例
公共类子扩展(可选){
私人T;
公共无效集(T){
t=t;
}
}

声明
Optional
final可以防止创建像上面这样的子类,从而保证
Optional
始终是不可变的。

正如其他人所说,Optional是一个基于值的类,因为它是一个基于值的类,所以它应该是不可变的,这需要它是final


但我们没有抓住重点。基于值的类不可变的一个主要原因是保证线程安全。使其不可变使其线程安全。例如字符串或基本包装,如整数或浮点。由于类似的原因,它们被声明为final。

尽管我们不能扩展可选类,但我们可以创建自己的包装类

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();

    }

}
public-final-class选项{
私人Opt(){
}
公共静态最终流填充删除(T){
返回可选的.ofNullable(t).isPresent()?Stream.of(t):Stream.empty();
}
}

希望它能帮助你。很高兴看到反应

关于第二个问题:
final
类a中的所有方法都隐式地
final
@assylias这不是问题,尽管我会尝试探究它,并找出为什么它在这里没有帮助。@kocko是的,这是真的,然而,为什么在这种情况下类本身需要是final呢?如果所有方法都是
final
,并且类本身是非final的,那么这仍然是可能的,除非我弄错了。诚然,对于
String
,也可以这样说。Java倾向于有点法西斯,以保护您不做错事那么,因为有人可能重写类使其可变,所以规范不允许子类?这让我恼火的原因是,我想用可选流替换异常流,这样我们就不必返回值或抛出异常,而只能返回可选流并将异常附加到错误流中,可能需要添加
ifError(Consumer-Consumer)
getCause()
方法。在我看来,这是对传统继承的一个很好的利用:扩展——但不是使原来的行为无效。遗憾的是,我做不到。对我来说,相对于原始状态,它仍然是不变的。@Groostav提出的案例正是我的案例,对我来说,这似乎是一个完全有效的案例。它遵循Optional强加的契约,并且它对Optional的现有用法是透明的,这是组合或例外所不能做到的。@neXus,自从写了这篇评论之后,我转到了kotlin(kotlinlang.org),并使用了他们的许多解决方案之一来解决这个问题。在
s()和
任一
之间,这是一个已解决的问题。。。对于JVM上除java之外的所有人来说都是这样。如果
t
null
,则会抛出
NullPointerException