【问题标题】:Wrapping null-returning method in Java with Option in Scala?用Scala中的Option包装Java中的空返回方法?
【发布时间】:2011-06-09 05:09:48
【问题描述】:

假设我有一个方法session.get(str: String): String,但你不知道它会返回一个字符串还是一个空值,因为它来自Java。

在 Scala 中是否有更简单的方法来处理这个问题而不是 session.get("foo") == null ?也许像ToOption(session.get("foo")) 这样应用了一些魔法,然后我可以像

一样以 Scala 方式处理它
ToOption(session.get("foo")) match {
    case Some(_) =>;
    case None =>;
}

【问题讨论】:

标签: java scala scala-option


【解决方案1】:

Option 伴随对象的 apply 方法用作可空引用的转换函数:

scala> Option(null)
res4: Option[Null] = None

scala> Option(3)   
res5: Option[Int] = Some(3)

【讨论】:

    【解决方案2】:

    Option 对象有一个 apply 方法可以做到这一点:

    var myOptionalString = Option(session.get("foo"));
    

    【讨论】:

      【解决方案3】:

      请注意,使用 Java 对象时,它不会按预期工作:

      val nullValueInteger : java.lang.Integer = null
      val option: Option[Int] = Option(nullValueInteger)
      println(option)  // Doesn't work - zero value on conversion
      
      val nullStringValue : String = null
      val optionString: Option[String] = Option(nullStringValue)
      println(optionString) // Works - None value
      

      【讨论】:

      • 我使用 scala 2.11.8 运行。第二行抛出 NullPointerException。第六行得到 Some(null),而不是你预期的 None。
      • 1.在 optionString 中使用 Some 而不是 Option - 更改了原始答案。 2. 仅在 Scala 2.12.5 中验证
      【解决方案4】:

      这是一个非常古老的话题,但很好!

      确实,将 Try 的任何 Non-exception 结果转换为 Option 都会导致 Some...

      scala> Try(null).toOption
      res10: Option[Null] = Some(null)
      

      ...因为 Try 不是关于可空性检查,而只是一种在功能上处理异常的方法。

      使用 Try 捕获异常并将其转换为 Option 以便于方便只会在发生异常时显示 None。

      scala> Try(1/0).toOption
      res11: Option[Int] = None
      

      您希望保留 Try 产生的值。那可能是空的。

      但标准库有时也很令人困惑......

      scala> Try(null).toOption
      res12: Option[Null] = Some(null)
      
      scala> Option(null)
      res13: Option[Null] = None
      

      这种行为有点不一致,但它反映了 Try 和 Option 的意图用法。

      您使用 try 从可能引发异常的表达式中获取任何内容,而您并不关心异常本身。

      可能出现的值很可能是空值。如果 toOption 给出了 None,你无法区分异常和 null,这并不漂亮!

      Standalone,你使用 Option 来封装某物的存在与否。所以在那种情况下 Some(null) 是 None,这是有道理的,因为在这种情况下 null 表示缺少某些东西。这里没有歧义。

      重要的是要注意,在任何情况下都不会破坏参考透明度,因为 .toOption 与 Option() 相同

      如果您确实需要执行 BOTH 异常安全AND null 安全,并且您的代码真的不需要区分 null 和异常,你只需要结合这两种范式!因为好吧,这就是你想要的,对吧?

      你可以用一种方式做到这一点......

      scala> Try(Option(null)).getOrElse(None)
      res23: Option[Null] = None
      
      scala> Try(Option(3/0)).getOrElse(None)
      res24: Option[Int] = None
      
      scala> Try(Option(3)).getOrElse(None)
      res25: Option[Int] = Some(3)
      

      ...或其他...

      scala> Try(Option(null)).toOption.flatten
      res26: Option[Null] = None
      
      scala> Try(Option(3/0)).toOption.flatten
      res27: Option[Int] = None
      
      scala> Try(Option(3)).toOption.flatten
      res28: Option[Int] = Some(3)
      

      ...或者他们中最丑陋的另一个...

      scala> Option(Try(null).getOrElse(null))
      res29: Option[Null] = None
      
      scala> Option(Try(3/0).getOrElse(null))
      res30: Option[Any] = None
      
      scala> Option(Try(3).getOrElse(null))
      res31: Option[Any] = Some(3)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-05
        • 1970-01-01
        • 2016-08-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-27
        相关资源
        最近更新 更多