用Scala中的Option包装Java中的空返回方法?

Posted

技术标签:

【中文标题】用Scala中的Option包装Java中的空返回方法?【英文标题】:Wrapping null-returning method in Java with Option in Scala? 【发布时间】: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 =>;

【问题讨论】:

更多Option技巧见blog.tmorris.net/scalaoption-cheat-sheet 上面的链接应该是blog.tmorris.net/posts/scalaoption-cheat-sheet。 【参考方案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)

【讨论】:

以上是关于用Scala中的Option包装Java中的空返回方法?的主要内容,如果未能解决你的问题,请参考以下文章

scala-从入门到精通

以有效的方式从scala中的序列中过滤选项

我们应该使用 Option 还是 ptr::null 来表示 Rust 中的空指针?

如何为scala中的空数据框现有列添加赋值?

初学scala1——Option

Java8 中的Optional类详解