这是一个非常古老的话题,但很好!
确实,将 Try 的任何非异常结果转换为 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,这可不漂亮!
独立时,您使用 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)