I’m converting someone else’s java code to scala (for the curious, it’s the example here) and I hit a compiler error on the following (simplified somewhat):
var out = new Formatter(new StringBuilder(), Locale.US)
out.format("%s-%d ", someObject, someInteger);
And here’s the error message I get:
[error] (java.util.Locale,java.lang.String,<repeated...>
[java.lang.Object])java.util.Formatter <and>
[error] (java.lang.String,<repeated...>[java.lang.Object])java.util.Formatter
[error] cannot be applied to (java.lang.String, java.lang.Object, Int)
...
[error] one error found
This works if I change the second line to:
out.format("%s-%d ", someObject, someInteger.asInstanceOf[Object]);
Can someone explain why this is?
Does this mean that it’s ok in java to pass integers where object arguments are expected but not in scala?
The other answers all add something, but I’m not sure they explain what the problem is.
It all comes down to
Intbeing a class in Scala whileintis a primitive in Java. So, in Java, when you write that a method expects anObject, and you pass anint, Java will auto-box it in ajava.lang.Integer.Now, Java’s
java.lang.Objectequivalent in Scala isAnyRef, butIntis not a subclass ofAnyRef. There’s a proper type for that:Any. AnAnycan contain both things which are subclasses ofjava.lang.Objectas well as the stuff that are primitives in Java. If you say a method expectsAnyand pass anInt, then it will be auto-boxed, but not forAnyRef.So, whenever you interface with Java and a method expects you to pass boxed primitives, you’ll have to force the boxing yourself. You can create a method expecting
Anyin Scala, and then cast it toAnyRefand call the Java equivalent, to make things easier if you are going to call that method a lot.