0

java.util.concurrent.ConcurrentMap's putIfAbsent docs say the following about the return type:

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

On Scala 2.10.4, I tried to call putIfAbsent(Int, Int), i.e. with Scala's Int type.

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

Since 1 does not exist in the empty ConcurrentHashMap, I would expect null to return from a putIfAbsent(x, x) call.

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

But, 0 gets returned. I'm assuming that null gets converted to 0.

What exactly is going on here? It seems odd to me that it's compiling.

1 Answer 1

2

Int cannot be null, nor can any AnyVal. From the 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.

If we try it directly, we'll get an error:

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

The compiler instead fills it with the default value for Int, which is 0.

For example:

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

scala> getNull(1)
res6: Int = 0

Behind the scenes, we can't actually cast null to an Int, but it can be cast to a boxed type. However, once we use the boxed type in a context where it should be like the primitive it contains, it's converted to that type, which requires a default value.

3
  • Thanks for this detailed answer. You explained how a Scala Int can't be null. Given the Scala method: def f(x: Int): java.lang.Integer and a Java method, public static int g, is true that f( g ) will never return null? Commented Feb 28, 2015 at 15:36
  • java.lang.Integer is a class, so it can be null. Commented Feb 28, 2015 at 17:24
  • Yes, it does. Sorry for the delay. Thanks for your help on all of my questions. Commented Mar 17, 2015 at 17:27

Not the answer you're looking for? Browse other questions tagged or ask your own question.