ConcurrentMap#putIfAbsent 与 Scala Int 的

ConcurrentMap#putIfAbsent with Scala Int's

java.util.concurrent.ConcurrentMapputIfAbsent 文档对 return 类型的描述如下:

the previous value associated with the specified key, or null if there was no mapping for the key.

在 Scala 2.10.4 上,我尝试调用 putIfAbsent(Int, Int),即使用 Scala 的 Int 类型。

scala> import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentHashMap

scala> new ConcurrentHashMap[Int, Int]()
res0: java.util.concurrent.ConcurrentHashMap[Int,Int] = {}

scala> val x: Int = 1
x: Int = 1

由于 1 不存在于空的 ConcurrentHashMap 中,我希望 null 到 return 来自 putIfAbsent(x, x) 调用。

scala> res0.putIfAbsent(x, x)
res1: Int = 0

但是,0 得到了 returned。我假设 null 转换为 0.

这里到底发生了什么?它正在编译对我来说似乎很奇怪。

Int 不能是 null,也不能是 AnyVal。来自 scaladoc:

Null is a subtype of all reference types; its only instance is the null reference. Since Null is not a subtype of value types, null is not a member of any such type. For instance, it is not possible to assign null to a variable of type scala.Int.

如果直接尝试,会报错:

scala> val i: AnyVal = null
<console>:9: error: type mismatch;
 found   : Null(null)
 required: AnyVal
Note that implicit conversions are not applicable because they are ambiguous:
 both method RichException in object Predef of type (self: Throwable)RichException
 and method augmentString in object Predef of type (x: String)scala.collection.immutable.StringOps
 are possible conversion functions from Null(null) to AnyVal
       val i: AnyVal = null

编译器改为使用 Int 的默认值填充它,即 0

例如:

scala> def getNull[A](i: A): A = null.asInstanceOf[A]
getNull: [A](i: A)A

scala> getNull(1)
res6: Int = 0

在幕后,我们实际上无法将 null 转换为 Int,但可以将其转换为盒装类型。但是,一旦我们在上下文中使用装箱类型,它应该像它包含的原始类型一样,它就会转换为需要默认值的类型。