I have some Scala code that needs to call a Java API
The Java API takes arguments that may be null. My Scala, of course, uses Option
.
For example, let's say I have a Java object constructor Foo(Integer)
where the Integer
may be null
. I want to call it given a Scala bar: Option[Int]
.
I tried this
import scala.collection.JavaConversions._
import scala.collection.JavaConverters._
val foo = Foo( bar.getOrElse(null) )
But got this compile error
Error:(335, 44) type mismatch;
found : Any
required: Integer
bar.getOrElse(null),
What is the correct idiom for doing this?
You don't need a Java method to reproduce this problem:
scala> import scala.collection.JavaConversions._
import scala.collection.JavaConversions._
scala> import scala.collection.JavaConverters._
import scala.collection.JavaConverters._
scala> class Foo(a: java.lang.Integer)
defined class Foo
scala> val bar: Option[Int] = Some(5)
bar: Option[Int] = Some(5)
scala> new Foo(bar.getOrElse(null))
<console>:16: error: type mismatch;
found : Any
required: Integer
new Foo(bar.getOrElse(null))
^
The problem is that Int
can't be null
, so the type of bar.getOrElse(null)
is Any
.
scala> bar.getOrElse(null)
res0: Any = 5
scala> bar.orNull
<console>:15: error: Cannot prove that Null <:< Int.
bar.orNull
^
So you've got to convert the Option
's type parameter to something that can be null
before you unwrap it in a nullable way.
Quickest way I can think of immediately:
scala> new Foo(bar.map(x => x: java.lang.Integer).orNull)
res18: Foo = Foo@cdc45e
Edit: Here, I thought of a more general way to do it!
implicit class RichOption[A](o: Option[A]) {
def toRef[B >: Null](implicit f: A => B): B = o.map(f).orNull
}
Now you can write new Foo(bar.toRef)
:)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With