13

This should be an obvious one but I've not yet found an elegant solution. For various reasons, I need to create an immutable Scala map (scala.collection.immutable.Map from Scala 2.10), but I can only write Java code. How do I do this?

1
  • He wants to create a scala map in java, not the opposite. Commented Jan 16, 2013 at 18:32

2 Answers 2

19

Wild guess - here goes nothing:

scala.collection.immutable.Map$.MODULE$.<…, …>empty()
Sign up to request clarification or add additional context in comments.

6 Comments

Do you really need to go through MODULE by hand? As far as I know there are forwarder static methods that already do this. Can't check right now though, I have no compiler at hand.
My bad, you do need to access Map$ instead of Map but accessing MODULE$ by hand is unnecessary.
@Regis, according to my compiler, even the MODULE$ part is required, unfortunately.
Huh, weird. I'll have to check that. Sorry for the noise, I should try to refrain from posting without having a compiler at hand for verification.
The generics parameters should go before the function name: scala.collection.immutable.Map$.MODULE$.<String, String>empty();
|
2

At first I was puzzled that just doing the following would fail:

scala.collection.immutable.Map<Integer, String> = scala.collection.immutable.Map$.<Integer, String>empty();

The reason it seemed odd is because I know for a fact that scala generates static forwarders that internally dereference MODULE$ and call the corresponding (non-static) method. I made some tests, and although what I found is somewhat tangential to the original question, it is still related and good to know.

Say we have the following:

package test
object MyScalaObject {
  def empty[A, B]: Map[A, B] = sys.error("TODO")
}

Using javap we can see that a static forwarder is generated:

public class test.MyScalaObject extends java.lang.Object{
    public static scala.collection.immutable.Map empty();
    public test.MyScalaObject();
}

And indeed we can in java just do the following:

scala.collection.immutable.Map<Integer, String> myMap = test.MyScalaObject.<Integer, String>empty();

All is well and nice. However, if we add a class or trait MyScalaObject that also defines a method with the same signature, no static forwarder is generated by scala (certainly because the JVM does not allow a class to define both a static and non-static method with the same signature). There are probably other different subtle situations that prevent the static forwarders to be generated.

Consider:

package test
class MyScalaObject {
  def empty[A, B]: Map[A, B] = sys.error("TODO")
}
object MyScalaObject {
  def empty[A, B]: Map[A, B] = sys.error("TODO TOO")
}

javap shows that the static forwarder has indeed disappeared:

public class test.MyScalaObject extends java.lang.Object{
    public scala.collection.immutable.Map empty();
    public test.MyScalaObject();
}

In this case it means that we have to explictly dereference $MODULE which points to the (unique) instance of the singleton object:

scala.collection.immutable.Map<Integer, String> myMap = test.MyScalaObject$.MODULE$.<Integer, String>empty();

As it turns out, both the trait scala.collection.immutable.Map and its companion object define a parameterless empty method, so we stumble upon this very issue.

The moral is that while static forwarders are a potentially useful feature, it is also very fragile because the mere fact of modifying a class (in this case adding an empty method in class MyScalaObject) can break the feature, without even touching its companion object itself. It is thus certainly a good idea to always explicitly reference MODULE$ (as in Wilfred Springer's answer) even if it looks less nice and even if the static forwarder is currently present, to prevent potential breakage when updating to a newer version of the library.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.