请解释使用Option的orNull方法

Dav*_*vid 18 api scala scala-java-interop

Scala的Option类有一个orNull方法,其签名如下所示.

orNull [A1 >: A](implicit ev : <:<[Null, A1]) : A1
Run Code Online (Sandbox Code Playgroud)

我被隐含的东西弄糊涂了.有人请说明如何使用它,理想情况下是一个例子吗?

Itt*_*ayD 31

scala> Some(1).orNull
<console>:10: error: could not find implicit value for parameter ev: <:<[Null,Int]
       Some(1).orNull
               ^
scala> (None : Option[Int]).orNull
<console>:10: error: could not find implicit value for parameter ev: <:<[Null,Int]
       (None : Option[Int]).orNull

scala> Some("hi").orNull
res21: java.lang.String = hi

scala> Some(null : String).orNull
res22: String = null

scala> (None : Option[String]).orNull
res23: String = null
Run Code Online (Sandbox Code Playgroud)

为了解释隐含的东西:orNull是获得来自一些回来的路|无成语Java的价值|空成语(这是当然的,坏).现在只有AnyRef值(类的实例)可以接受空值.

所以我们会喜欢的是def orNull[A >: Null] = .....但是A已经设置好了,我们不想在特征的定义中限制它.因此,orNull期望证明A是可以为空的类型.这个证据是一个隐含变量的形式(因此名称'ev')

<:<[Null, A1]可以写成这样Null <:< A1看,它类似于'Null <:A1'.<:<在Predef中定义,以及提供名为的隐式值的方法conforms.

我认为这里并不严格要求使用A1,因为orNull使用getOrElse(默认给定的可以是A的超类型)

scala> class Wrapper[A](option: Option[A]) {
     | def orNull(implicit ev: Null <:< A): A = if(option.isEmpty) null else option.get
     | }
defined class Wrapper

scala> new Wrapper(Some("hi")).orNull
res18: java.lang.String = hi
Run Code Online (Sandbox Code Playgroud)

  • 看到这样的东西,实际上很难不爱斯卡拉. (5认同)
  • 图书馆作家在很大程度上使所有模块化并且工作得很好; 缺点是签名对于局外人来说通常看起来非常奇怪,并且错误消息是难以理解的.一个好的提示可能是忽略它,只是阅读文档.:-) (4认同)

Vas*_*iuk 5

orNull目的首先是确保Option与Java的兼容性.虽然null在Scala中不鼓励使用,但某些接口可能会获得可以为空的引用.

orNull 有一个简单的实现:

def orNull[A1 >: A](implicit ev: Null <:< A1): A1 = this getOrElse null
Run Code Online (Sandbox Code Playgroud)

根据这个,null不仅会返回boxed nulls(Some(null)),而且还会返回None(例如,如果你调用None.get,将抛出异常).

如果装箱值可以为空,则进行隐式参数检查.

良好的用法示例可以在评论中找到orNull:

val initialText: Option[String] = getInitialText
val textField = new JComponent(initialText.orNull,20)
Run Code Online (Sandbox Code Playgroud)

  • 只是为了使其更加明确:这仅适用于引用类型(AnyRef的子类型),而不适用于值类型(AnyVal的子类型),因为它们没有空值。 (2认同)
  • 然后,您需要使用类型说明,显式指定`java.lang.Long`而不是`scala.Long`:`val initialText:Option [java.lang.Long] = getInitialLong` (2认同)