scala泛型约束如何对可空类型起作用

Dan*_*ock 14 generics scala nullable constraints

我已经尝试了两种方法将泛型类型参数约束为可空类型,但两者似乎都有一些意想不到的问题.

第一次尝试(使用T <:AnyRef):

scala> def testAnyRefConstraint[T <: AnyRef](option:Option[T]):T = {
     | //without the cast, fails with compiler error:
     | //    "found: Null(null) required: T"
     | option getOrElse null.asInstanceOf[T]
     | }
testAnyRefConstraint: [T <: AnyRef](Option[T])T

scala> testAnyRefConstraint(Some(""))
res0: java.lang.String = 

scala> testAnyRefConstraint(Some(0))
<console>:16: error: inferred type arguments [Int] do not conform to method testAnyRefConstraint's type parameter bounds [T <: AnyRef]
       testAnyRefConstraint(Some(0))
Run Code Online (Sandbox Code Playgroud)

这似乎完全符合我的要求,但我不明白为什么需要将null转换为T.


第二次尝试(使用T>:Null):

scala> def testNullConstraint[T >: Null](option:Option[T]):T = {
     | option getOrElse null
     | }
testNullConstraint: [T >: Null](Option[T])T

scala> testNullConstraint(Some(""))
res2: java.lang.String = 

scala> testNullConstraint(Some(0))
res3: Any = 0
Run Code Online (Sandbox Code Playgroud)

这不需要在null上进行强制转换,但它允许传递AnyVals并将类型转换为any,这不是我想要的.

有谁知道为什么这两种不同的方法按照他们的方式工作?

Dan*_*ral 23

def testAnyRefConstraint[T >: Null <: AnyRef](option:Option[T]):T = {
  option getOrElse null
}
Run Code Online (Sandbox Code Playgroud)

当我第一次犯这个错误时,我觉得非常愚蠢.仅仅因为某些东西延伸AnyRef并不意味着它必须是可空的.例如,Nothing是子类型AnyRef,并且它不可为空.

Any反过来是相似的,因为是超类型Null,任何Int也是一个Any.