scala 请说明Option的orNull方法的使用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4467601/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Please explain use of Option's orNull method
提问by David
Scala's Option class has an orNullmethod, whose signature is shown below.
Scala 的 Option 类有一个orNull方法,其签名如下所示。
orNull [A1 >: A](implicit ev : <:<[Null, A1]) : A1
I'm bewildered by the implicit thing. Would somebody please explain how it can be used, ideally with an example?
我对隐含的东西感到困惑。有人可以解释一下如何使用它,最好是举例说明吗?
回答by IttayD
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
To explain the implicit thing: orNull is a way of getting back from the Some|None idiom to Java's value|null idiom (which is, of course, bad). Now only AnyRef values (instances of classes) can accept a null value.
解释隐含的事情: orNull 是一种从 Some|None 习语恢复到 Java 的 value|null 习语(当然,这是不好的)的方法。现在只有 AnyRef 值(类的实例)可以接受空值。
So what we would have liked is def orNull[A >: Null] = ..... But A is already set and we don't want to restrict it in the definition of the trait. Therefore, orNull expects an evidence that A is a nullable type. This evidence is in the form of an implicit variable (hence the name 'ev')
所以我们会喜欢的是def orNull[A >: Null] = ..... 但是 A 已经设置了,我们不想在特征的定义中限制它。因此, orNull 期望有证据表明 A 是可空类型。该证据采用隐式变量的形式(因此名称为“ ev”)
<:<[Null, A1]can be written as Null <:< A1seeing it like this, it is similar to 'Null <: A1'. <:< is defined in Predef as well as the method that provides the implicit value named conforms.
<:<[Null, A1]可以写成这样Null <:< A1看,类似于'Null <: A1'。<:< 在 Predef 以及提供名为 的隐式值的方法中定义conforms。
I think the use of A1 is not strictly required here and is because orNull uses getOrElse (where the default given can be a super type of A)
我认为这里并不严格要求使用 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
回答by Vasil Remeniuk
orNullpurpose is first of all in ensuring compatibility of Optionwith Java. Though usage of nullis discouraged in Scala, some interfaces may expect to get nullable references.
orNull目的首先是确保Option与Java的兼容性。尽管null在 Scala 中不鼓励使用 of ,但某些接口可能希望获得可空引用。
orNullhas a straightforward implementation:
orNull有一个简单的实现:
def orNull[A1 >: A](implicit ev: Null <:< A1): A1 = this getOrElse null
According to this, nullwill be returned not only for boxed nulls (Some(null)), but also for None(e.g., if you call None.get, exception will be thrown).
据此,null不仅会为装箱的空值 ( Some(null)) 返回,还会为None(例如,如果您调用None.get,则会抛出异常)。
Implicit parameter checks, if the boxed value is nullable.
隐式参数检查,如果装箱值可以为空。
Good usage example can be found right in the comments to orNull:
可以在以下评论中orNull找到好的用法示例:
val initialText: Option[String] = getInitialText
val textField = new JComponent(initialText.orNull,20)
回答by Kris Nuttycombe
Remember that in Scala primitive types and reference types are unified - but only reference types are nullable. The implicit simply allows the compiler to confirm that A1 is a reference type.
请记住,在 Scala 中,原始类型和引用类型是统一的——但只有引用类型可以为空。隐式只是允许编译器确认 A1 是引用类型。
回答by weberste
To understand why it is useful, IttayD provided a nice explanation:
为了理解它为什么有用,IttayD 提供了一个很好的解释:
So what we would have liked is def
orNull[A >: Null] = .....But A is already set and we don't want to restrict it in the definition of the trait. Therefore, orNull expects an evidence that A is a nullable type. This evidence is in the form of an implicit variable (hence the name 'ev')
所以我们想要的是 def
orNull[A >: Null] = .....但是 A 已经设置了,我们不想在特征的定义中限制它。因此, orNull 期望有证据表明 A 是可空类型。该证据采用隐式变量的形式(因此名称为“ ev”)
In summary, type constraints are useful when you want have methods (eg orNull) on a generic class (eg Option) with more specific constraints (eg Null <: A <: Any) than on the class itself (eg A <: Any).
总之,当您希望在具有比类本身(例如)更具体的约束(例如)orNull的泛型类(例如)上拥有方法(例如)时,类型约束很有用。OptionNull <: A <: AnyA <: Any
This is another "feature" that is not built into the language but comes for free thanks to implicit parameters and variance annotations of type parameters. To understand this, look at the definition of <:<:
这是另一个未内置于语言中的“功能”,但由于隐式参数和类型参数的方差注释而免费提供。要理解这一点,请查看 的定义<:<:
// from Predef
sealed abstract class <:<[-From, +To] extends (From => To)
implicit def conforms[A]: A <:< A = new (A <:< A) {def apply(x: A) = x}
For
为了
scala> Some(1).orNull
<console>:10: error: could not find implicit value for parameter ev: <:<[Null,Int]
Some(1).orNull
the compiler looks for an implicit value of type <:<[Null, Int]and will find the method def conforms[A]: A <:< A. So there has to be an Afor which <:<[A, A]conforms to <:<[Null, Int]. There is no Afor which this holds and as a result the compiler will complain about the missing implicit value.
编译器查找 type 的隐式值<:<[Null, Int]并找到方法def conforms[A]: A <:< A。因此,必须有一个A针对<:<[A, A]符合<:<[Null, Int]。不存在A这种情况,因此编译器会抱怨缺少隐式值。
However, for
然而,对于
scala> Some("hi").orNull
res21: java.lang.String = hi
we are lucky. Now, the compiler tries to find an Afor which <:<[A, A]conforms to <:<[Null, String]. This works for A = String, because Nullis a subtype of Stringand the Fromtype parameter of the class <:<is defined as contravariant).
我们很幸运。现在,编译器试图找到一个A针对<:<[A, A]符合<:<[Null, String]。这适用于A = String,因为Null是 的子类型String并且类的From类型参数<:<被定义为逆变)。
As mentioned, the most intuitive way to think about type constraints is reading it like a type bound (i.e. reading it as Null <: Int). Nulldoes not conform to Intand there is no implicit value for <:<[Null, Int]. On the other hand, Nulldoes conform to Stringand the compiler will find the implicit parameter.
如前所述,考虑类型约束的最直观方式是像类型绑定一样读取它(即,将其读取为 Null <: Int)。<:<[Null, Int]Null不符合Int且没有隐含值。另一方面,Null确实符合String并且编译器会找到隐式参数。
By the way, here is another related answer.
顺便说一句,这是另一个相关的答案。
回答by StuartLC
Re : 'how' is this used - one place we are finding this useful is when dealing with java api mappings where nullis commonplace, e.g. on jdbc prepared statements to nullable sql columns. The Optional internal model fields can be mapped:
Re: '如何' 是这样使用的 - 我们发现这很有用的一个地方是在处理 java api 映射时null很常见,例如在 jdbc 准备好的语句到可为空的 sql 列时。的Option人内部模型的字段可以被映射:
stmt.setDate("field", myModel.myDateField.orNull)
Instead of the more verbose:
而不是更冗长:
stmt.setDate("field", myModel.myDateField.getOrElse(null))

