Many years of using Scala and still I don't know the right way to interoperate with Java. :(
To be honest, this is not something that I'm doing every day, but sometimes there is no other option (today is Firestore Java libraries).
My question today is about the proper way to instantiate POJOs that can have null values.
At the end of the day, I always use something like the def toJavaLong(l: Option[Long]): java.lang.Long = if (l.isEmpty) l.get else null
, but pretty sure that there is a better and elegant way.
Please, could you show me the path? I expect something like orNull
working out of the box, but it is never the case.
I'm using Scala 2.13, but feel free to show alternatives to Scala 3 as well.
In the next example, I explain the errors that I have using orNull
and getOrElse
:
Pojo:
public class ExamplePojo {
public Long value;
public ExamplePojo(Long value) {
this.value = value;
}
}
Scala object instanciating the Pojo:
object CreatePojo {
def main(args: Array[String]): Unit = {
val noneValue = Option.empty[Long]
val oneValue = Some(1L)
def toJavaLong(l: Option[Long]): java.lang.Long =
if (l.isEmpty) l.get else null
// Next line works fine.
new ExamplePojo(toJavaLong(noneValue))
// Next line works fine of course, but not helpful. :)
new ExamplePojo(oneValue.get)
// Next line throws a compilation error:
// type arguments [Long] do not conform to method orNull's type parameter bounds [A1 >: Long]
new ExamplePojo(noneValue.orNull)
// Next line throws a compilation error:
// type mismatch;
// found : Any
// required: Long
new ExamplePojo(noneValue.getOrElse(null))
// This will throw a `java.util.NoSuchElementException`
new ExamplePojo(noneValue.get)
}
}
Of course, this is only an example to reproduce the case.
The problem, in this case, is not the null
, but the fact that scala.Long
is not the same as java.lang.Long
What you can do is the following:
new ExamplePojo(l.map(Long.box).orNull)