Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected behavior when creating Scala Option from java.lang.Long

Given following code:

val javaLong: java.lang.Long = null
val opt: Option[Long] = Option(javaLong)

I expected opt to be None but for some reason it is Some(0). I also found this bug and it appears that implicit conversion happens before option's apply method. I think this is still a bug because one wouldn't expect that behavior and I am wondering is there any workaround or some better ways to wrap nulls.

Update: The code above is only a simplified piece. The real example is something like:

Person(Option(doc.getLong()))

where Person is:

 case class Person(id: Option[Long])

and method doc.getLong() is java method that returns java.lang.Long

like image 306
Dmitry Kach Avatar asked Oct 10 '18 16:10

Dmitry Kach


1 Answers

The conversion to Option[Long] is actually not just a conversion to an Option but also an implicit cast to Scala's Long from Java's Long.

val javaLong: java.lang.Long = null
// javaLong: Long = null

val long: java.lang.Long = javaLong
// long: Long = null
val long: Long = javaLong
// long: Long = 0

First we have the implicit conversion from Java's Long to Scala's Long which apparently produces 0 out of null.

Only then do we have the conversion to an Option.

If we specify Java's Long as a type of our Option then we do get None and not Some(0):

val opt: Option[java.lang.Long] = Option(javaLong)
// opt: Option[Long] = None (here it's Java's Long)

And we can finally cast the Option[java.lang.Long] to use Scala's Long:

val opt: Option[Long] = Option(javaLong).map(_.toLong)
// opt: Option[Long] = None (here it's Scala's Long)
like image 55
Xavier Guihot Avatar answered Jan 03 '23 16:01

Xavier Guihot