Monday, 30 November 2009

Calling Scala Object Fields from Java

It's pretty easy to call anything in Java from Scala but sometimes it can be hard to go the other way round.

I work on a large codebase that contains both Java and Scala. All new development is done in Scala but sometimes we need to update a Java class by calling some Scala code. In most cases this is easy but sometimes I run into problems.

Say you have a Scala object like so:

object JavaCallingScalaTest {
val Constant = "Constant"
}
and you want to use the 'Constant' field in a Java file. You would do this like so:

public class JavaCallingScalaTestJavaFile {
private static final String CONSTANT = JavaCallingScalaTest$.MODULE$.Constant();
}
Now lets say the Scala field is a map like so:

object JavaCallingScalaTest {
val IntToString = Map(1 -> "one", 2 -> "two")
}
and you want to extract some information out of the map in Java, you would do something like this:

public class JavaCallingScalaTestJavaFile {
private static final String TEXT_FOR_TWO = JavaCallingScalaTest$.MODULE$.IntToString().apply(2);
}
Enjoy.

Monday, 16 November 2009

Scala Map Java Map and vice versa

I use a lot of Scala at work. It's a great language but one thing I don't like about the library in the current version (2.7.*) is the way it deals with (or doesn't for that matter) converting between Scala and Java collection classes (and vice versa). This is a big problem if you use Scala in anger as you will almost certainly have to interact with Java libraries. This is really disappointing as one of Scala's strengths is the way it can easily integrate with Java in most situations.

Luckily, I don't have to bother displaying all the extra code I've had to write to get this working in 2.7.* as this issue has been addressed in the upcoming 2.8 version.

The following code shows conversions both ways between Scala and Java maps:

object CollectionTest {
import scala.collection.JavaConversions._
import scala.collection.mutable.{Map => MMap}
import java.util.{Map => JMap}

def main(args: Array[String]) {
val scalaMap = MMap(1 -> "one", 2 -> "two", 3 -> "three")
println(scalaMap)

val convertedJavaMap: JMap[Int, String] = scalaMap
println(convertedJavaMap)

val convertedScalaMap: MMap[Int, String] = convertedJavaMap
println(convertedScalaMap)
}
}
I initially define a mutable Scala map and then assign it to a new val of type java.util.Map. I then assign this new Java map to a val of type scala.collection.mutable.Map. You can see from the output that the maps have been converted.

Easy!