【问题标题】:Is Java 8 missing an OptionalBoolean?Java 8 是否缺少 OptionalBoolean?
【发布时间】:2014-05-28 21:25:22
【问题描述】:

作为Optional* 的原始版本,Java 1.8 提供了OptionalIntOptionalLongOptionalDouble

但我找不到等效的 OptionalBoolean 类。

是否有任何技术原因反对使用OptionalBoolean

* Optional 可能存在也可能不存在值,用作null 的替代。

【问题讨论】:

  • 我想我们可以问同样的问题,为什么 OptionalCharOptionalByteOptionalShortOptionalFloat 也不见了。
  • This question 相关。
  • @user3580294 好吧,这句话是关于原始流的,但我假设相同的逻辑适用于原始 Optionals。
  • 对于试图将其作为骗子关闭的人:重复的答案并不意味着提出了重复的问题。

标签: java boolean monads java-8 optional


【解决方案1】:

这句话解释了原始流背后的考虑。我假设同样适用于原始 Optionals。简而言之,原始流(可能还有 Optionals)是出于性能原因而创建的。他们没有为所有 8 种原始类型创建它们以减少代码重复和接口污染。

引用lambda mailing list 中的 Brian Goetz 的话:

更笼统地说:专业化背后的哲学 原始流(例如,IntStream)充满了令人讨厌的权衡。 一方面,它有很多丑陋的代码重复,界面 污染等另一方面,任何类型的盒装操作算术 糟透了,没有减少整数的故事会很糟糕。 所以我们正处于一个艰难的角落,我们正在努力不让情况变得更糟。

不让事情变得更糟的诀窍 #1 是:我们没有做所有八个 原始类型。我们正在做 int、long 和 double;所有其他人 可以通过这些来模拟。可以说我们也可以摆脱 int ,但是 我们认为大多数 Java 开发人员还没有为此做好准备。是的,那里 将调用 Character,答案是“将其放入 int 中”。 (预计每个专业化的 JRE 足迹约为 100K。)

技巧 #2 是:我们使用原始流来公开在原始域中最好完成的事情(排序、归约),但不是 试图复制您在盒装域中可以做的所有事情。为了 例如,正如 Aleksey 指出的那样,没有 IntStream.into()。 (如果有 是,下一个问题将是“IntCollection 在哪里? 数组列表? IntConcurrentSkipListMap?) 意图是多流 可能以参考流开始并以原始流结束,但是 反之亦然。没关系,这减少了转换次数 需要(例如,int -> T 的映射没有重载,没有特殊化 int -> T 等的函数)

我应该提到,我在this question 的答案中找到了这句话。

【讨论】:

  • 请耐心等待 Java 9。
  • “每个专业化的 JRE 足迹预计约为 100K。”这可能适用于流;我希望Optional 的占用空间更小。
【解决方案2】:

boolean 值经常被用作参数。有效的 Java 第 2 版警告不要滥用布尔值。如果它们不是用于实际的布尔真/假参数,它们通常会导致代码可读性差。相反,作者 Joshua Bloch 试图说服人们使用双重价值 enum's:

首选二元素 enum 类型而不是 boolean 参数。它使您的代码更易于阅读和编写,尤其是在您使用支持自动完成的 IDE 时。此外,它还可以轻松地在以后添加更多选项。

大多数OptionalBoolean 实例可能会被错误地使用。这是不包括一个很好的理由。但我不能说——只有甲骨文可以——如果这就是它不在那里的原因。

【讨论】:

  • 那么忽略可能被滥用的语言特性是否已成为 Oracle 的策略?有点令人失望,尽管我并不特别关心 OptionalBoolean 的缺失。机器语言的制造者没有这样的政策也很好——我们只有 0 而没有 1。
  • 我喜欢那本书,我非常尊重约书亚。我也觉得你说的有道理。当 Joshua 在那本书中描述了覆盖和实现Object.equals(Object) 的好方法时,他说必须始终使用instanceof 运算符,并称使用getClass() 是“不可接受的”(第39 页)。我还注意到,Oracle 实现中的所有库代码都使用instanceof 运算符。我还没有找到getClass() 运算符的一个示例(它恰好是我在非库代码中最喜欢的)。因此,Joshua 关于这个话题的引述将非常有价值。
  • 我同意你的观点,我更喜欢 enum 而不是 boolean 值作为方法调用的“选项”。我需要的是一个三态布尔值,它可以代表“任何”或“不确定”状态。从 Java 1.8 开始我就讨厌空值 =)
  • @owlstead 有人检查过异常吗?
  • @Eran up on the question cmets found another question,其接受的答案可能会回答这个问题。 tl;博士:this
【解决方案3】:

除了希望减少原始类型专业化类的组合爆炸的幅度之外,我怀疑缺少OptionalBoolean 的一个主要原因是,此类的优势远小于专业化的优势数字类型。

优势较小的原因是boolean类型只有两个不同的值。正因为如此,大多数时候你只能得到两个Boolean 类型的对象。这两个缓存为 Boolean.TRUEBoolean.FALSE 并在大多数情况下重用,例如当booleans 被自动装箱时。数值包装器类型为小范围的值有许多缓存对象,对于其他值,每次将原始值存储在通用容器(例如Optional)中时都必须分配一个新对象。

所以Optional<Boolean> 对象几乎与OptionalBoolean 一样有效,因为无需分配新的Boolean 即可将未装箱的boolean 放入其中。

如果在标准库的某处提供两个已兑现的Optional<Boolean>,我也很有用,可能是Optional.TRUE/FALSE。我不知道为什么没有。

【讨论】:

  • Boolean 不会被分配,但Optional<T> 会。与OptionalBoolean 实现相比,可以实现为{oTrue, oFalse, none} 的枚举,这仍然会占用更大的内存。
【解决方案4】:

为了完整一点:在 Java 8 中确实有一个 OptionalBoolean,但不是您所期望的:它是 com.sun.javafx.scene.control.behavior.OptionalBoolean

但是,虽然 JavaFX 现在是 Java 的固定组件,但不建议在 JavaFX 之外使用它。

除此之外,它的界面与你在java.util.*的界面完全不同。

【讨论】:

  • 不确定这是否应该是一个注释,但不管它是什么,对于那些依赖于 IDE 中完成的人来说,这绝对是一个很好的警告,例如 Eclipse、NetBeans 和类似的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-31
  • 1970-01-01
  • 2014-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多