用 Scala 中的选项在 Java 中包装 null 返回方法?

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

Is there an easier way to treat this in Scala instead of session.get("foo") == null ? Maybe some magic apply like ToOption(session.get("foo")) and then I can treat it in Scala way like

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

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

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


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

Option对象有一个 apply方法,正是这样做的:

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

注意,当使用 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> Try(null).toOption
res10: Option[Null] = Some(null)

... 因为 Try 不是关于空性检查,而只是一种处理异常的函数方法。

Using Try to catch an exception and converting that to an Option for convenience will only show None in case an exception happens.

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

您需要保留从“尝试”输出的值。该值可能为空。

但是标准的 lib 有时候确实很让人困惑。

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


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

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

您使用 try 来获取表达式中可能抛出异常的内容,并且不关心异常本身。

可能出现的值很可能是空值。如果选择给无,无法区分异常和 null,这是不漂亮的!

独立地,您可以使用 Option 来封装某些内容的存在与否。所以在这种情况下 Some (null)是 Nothing,这是有意义的,因为在这种情况下 null 表示缺少某些东西。这里没有歧义。

It's important to remark that in any case referencial transparency is not broken since .toOption is 没有 the same as Option()

如果您真的需要强制 都有异常安全 还有空安全,您的代码 真的不需要区分 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)