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

Why should I not use identity based operations on Optional in Java8?

java.util.Optional 的 javadoc 指出:

This is a value-based class; use of identity-sensitive operations (including reference equality (==), identity hash code, or synchronization) on instances of Optional may have unpredictable results and should be avoided.

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

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

Optional.of() 为每个非空值创建一个新对象。所以比较2个Optional很可能是两个引用,即使Optional引用的是同一个值

但是,您的示例表明 Optional.empty() 重复使用相同的单例实例。这可能是唯一一次相同的 Optional 实例被返回两次。

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

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

这类似于由包装类型的装箱 valueOf 方法编辑的实例 return。除了为某些(小)值创建的 gua运行ty 之外,未指定是创建新实例还是为相同的值returned 相同的实例。

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