为什么我不应该在Java8中对Optional使用基于身份的操作?

时间:2015-02-12 21:05:53

标签: java-8

java.util.Optional的javadoc声明:

  

这是一个基于价值的课程;在Optional的实例上使用身份敏感操作(包括引用相等(==),标识哈希代码或同步)可能会产生不可预测的结果,应该避免使用。

但是,这个junit片段是绿色的。为什么?它似乎与javadoc相矛盾。

    Optional<String> holder = Optional.ofNullable(null);
    assertEquals("==", true, holder == Optional.<String>empty());
    assertEquals("equals", true, holder.equals(Optional.<String>empty()));

2 个答案:

答案 0 :(得分:6)

您不应该从在特定实现下运行的一个简单测试的观察到的行为得出任何结论。规范说你不能依赖这种行为,因为API设计者保留自己随时改变行为的选项,恕不另行通知。

术语Value-based Class已经提供了有关预期选项的提示。当进行具有相同值的重复调用时,未来版本或替代实现可能返回相同的实例,或者JVM可能实现基于身份的操作没有意义的真值类型。

这类似于包装类型的装箱valueOf方法返回的实例。除了为某些(小)值所做的保证之外,未指定是创建新实例还是为相同值返回相同的实例。

“如果程序尝试将两个引用区分为基于值的类的相等值,则程序可能会产生不可预测的结果......”也可能意味着参考比较的结果可能会在生命周期内更改两个基于值的类实例。考虑重复数据删除功能。由于JVM已经为char[]的内部String数组提供了这样的功能,因此将此功能扩展到“基于值的类”的所有实例的想法并不是那么牵强。 / p>

答案 1 :(得分:0)

Optional.of()为每个非null值创建一个新Object。因此,即使Optional引用相同的值,比较2个Optionals也很可能是两个引用。

但是,您的示例显示Optional.empty()重新使用相同的单例实例。这可能是同一个Optional实例再次返回两次的唯一时间。