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

120

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

有没有更简单的方法在Scala中处理这个问题?比如像ToOption(session.get("foo"))这样的神奇应用程序,然后我可以按照Scala的方式处理它。

ToOption(session.get("foo")) match {
    case Some(_) =>;
    case None =>;
}

4
了解更多选项技巧,请查看http://blog.tmorris.net/scalaoption-cheat-sheet/。 - Landei
5
上面的链接应该是 http://blog.tmorris.net/posts/scalaoption-cheat-sheet/。 - Jacek Laskowski
4个回答

211

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

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

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

20

Option对象有一个apply方法,可以执行这个操作:

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

5
注意,当使用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

1
我使用的是Scala 2.11.8版本。第二行代码抛出了NullPointerException异常。第六行代码返回了Some(null),而不是你预期的None。 - John Lin
  1. 在optionString中使用Some而不是Option - 已更改原始答案。
  2. 仅在Scala 2.12.5中进行了验证。
- DekelM

-1

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

确实,将 Try 的任何非异常结果转换为 Option 将导致 Some...

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

...因为 Try 不是用于检查 nullability 的,而只是一种处理异常的函数式方式。

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

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

你想保留从Try中出来的值。这可能是null。

但也确实有时标准库相当令人困惑...

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

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

这种行为有点不一致,但它反映了 Try 和 Option 的预期使用方式。

你使用 try 来获取可能抛出异常的表达式的任何结果,并且你不关心异常本身。

可能出现的值很可能是 null。如果 toOption 给出 None,你无法区分异常和 null,这不太好!

独立使用时,你使用 Option 封装某些东西的存在或不存在。因此,在这种情况下,Some(null) 是 None,这是有意义的,因为在这种情况下,null 代表某些东西的缺失。这里没有歧义。

需要强调的是,在任何情况下,引用透明度都不会被破坏,因为 .toOption 不同于 Option()。

如果你真的需要强制实施异常安全性和 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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接