【问题标题】:What's the best way to retrieve the value in a nullable Optional?在可为空的 Optional 中检索值的最佳方法是什么?
【发布时间】:2020-04-05 01:08:00
【问题描述】:

假设您有一个 Optional<T> 变量,它可以采用 3 个值之一:

  • 值 T
  • 一个带有空 T 的 Optional
  • 变量本身为空

否则,检索值 Tnull 的最佳方法是什么?

这是一种方法:

Optional<String> op = ...
String str = op != null ? op.orElse(null) : null;

这是另一种方法:

String str = Optional.ofNullable(op).flatMap(innerOpt -> innerOpt).orElse(null);

各有什么优缺点?还有一个性能更好吗?是更多的scala-esque吗?是否更具可读性/可维护性?

【问题讨论】:

  • 一个 Optional 永远不应该为空。如果是这种情况,请不要解决它:修复代码。
  • 确实如此。一种可能的解决方法是使用Optional&lt;Optional&lt;T&gt;&gt; ;) 虽然如果您首先需要它,我会严重怀疑您的 model
  • 为什么这个标签是“scala”?这显然是一个 java 问题。
  • @BrianMcCutchon 是Java中空的定义,一个带有空值的Optional;没有。
  • @som-snytt Optional 的定义是“可能包含也可能不包含非空值的容器对象”(来自the JavaDoc)。一个空的 Optional 可以通过存储 null 来实现,但这是一个实现细节。 JavaDoc 始终使用诸如“如果存在值”和“空可选”之类的短语。我们应该避免使用诸如“空值”之类的模棱两可的语言,这听起来像是指的是Optional.of(null)(它会引发 NPE)。

标签: java scala java-8 functional-programming optional


【解决方案1】:

第一个可以简化为:

String str = op.orElse(null);

这将是你所写的最具可读性的可能性。

通常说Optional 不适合null 处理,但在我看来这只是个人喜好问题。假设你必须像在 kotlin 中那样进行链接:

object?.child?.grandChild

在每个级别上,我们都会执行一次空值检查。在java中它会是:

object == null ? null : (object.child == null ? null : object.child.grandChild)

这有点伤眼。它会写:

Optional.ofNullable(object)
    .map(Parent::getChild)
    .map(Child::getGrandChild)
    .orElse(null);

可能有点冗长,但对我来说 - 非常易读。正如我所说 - 这是一个品味问题。

P.S.:Optional 是一种通过将 null 包装在 monad 中来简化处理的方法。不要让Optional 成为null

【讨论】:

  • @Maarten-reinstateMonica 所以你会选择第一个选项?
  • 嗯,是的,但同样,问题的作者应该尝试修复他的代码。如果某个东西是null,这并不意味着您应该将另一个变量分配给null。一般来说,我希望有一个保护语句和一个运行时异常。任何时候任何人将null 分配给他们陷入陷阱的东西。
  • @Maarten-reinstateMonica 好的,所以这归结为不使用 null 作为特殊值。但并非总是有可能(例如与外部数据库集成)。如果我确实有一系列可能的nulls,我会认真考虑使用Optional。很抱歉听到我可能不理解可读性:)
  • 完全可读。不能同意“guard and throw”,但值得一提的是 OP 没有选择“throw null”。
  • @kane 没有沟通就没有编程(开发人员之间)。如果您不对混乱负责,请与负责的人交谈。不要因为没有人觉得自己有责任而将解决方法叠加在解决方法之上。
【解决方案2】:

证明 Scala 标签的合理性:

$ scala
Welcome to Scala 2.13.1 (OpenJDK 64-Bit Server VM, Java 11.0.3).
Type in expressions for evaluation. Or try :help.

scala> val x: java.util.Optional[String] = null
x: java.util.Optional[String] = null

scala> import scala.jdk.OptionConverters._
import scala.jdk.OptionConverters._

scala> Option(x).map(_.toScala).flatten.getOrElse("default")
res0: String = default

【讨论】:

    猜你喜欢
    • 2013-06-22
    • 1970-01-01
    • 2019-12-28
    • 2020-12-08
    • 1970-01-01
    • 2011-06-29
    • 1970-01-01
    • 2017-11-15
    • 1970-01-01
    相关资源
    最近更新 更多