假设我有一个方法session.get(str: String): String
,但由于它来自Java,你不知道它会返回字符串还是空值。
有没有更简单的方法在Scala中处理这个问题?比如像ToOption(session.get("foo"))
这样的神奇应用程序,然后我可以按照Scala的方式处理它。
ToOption(session.get("foo")) match {
case Some(_) =>;
case None =>;
}
假设我有一个方法session.get(str: String): String
,但由于它来自Java,你不知道它会返回字符串还是空值。
有没有更简单的方法在Scala中处理这个问题?比如像ToOption(session.get("foo"))
这样的神奇应用程序,然后我可以按照Scala的方式处理它。
ToOption(session.get("foo")) match {
case Some(_) =>;
case None =>;
}
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"));
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
这是一个非常古老的话题,但也是一个好话题!
确实,将 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)