I have the following code in Java:
public class JavaClass {
public static void method( Object x ) {
}
public static void varargsMethod( Object... x ) {
}
}
When I try and access it from Scala,
object FooUser {
JavaClass.method(true)
JavaClass.varargsMethod(true) // <-- compile error
}
I get the following compile error:
type mismatch; found : Boolean(true) required: java.lang.Object Note: primitive types are not implicitly converted to AnyRef. You can safely force boxing by casting x.asInstanceOf[AnyRef]
The error message is very helpful and shows how to fix the error, but I was wondering why the compiler is (apparently) happy to implicitly convert a scala.Boolean
in one method call but not the other. Is this a bug or intentional?
Updated to add: I'm using Scala 2.8. If I make the varargsMethod signature
public static <T> void varargsMethod(T... xs) {
instead, then the error also goes away. I'm still puzzled as to why the compiler can't 开发者_JAVA百科figure it out.
Scala varargs and Java varargs are different. You need to do a conversion:
def g(x: Any*) = x.asInstanceOf[scala.runtime.BoxedObjectArray]
.unbox(x.getClass)
.asInstanceOf[Array[Object]]
...
JavaClass.varargsMethod(g(true))
or (in 2.8.0+)
JavaClass.varargsMethod(java.util.Arrays.asList(true))
Since scala.Boolean
is a subclass of scala.AnyVal
but not scala.AnyRef
(translated to java.lang.Object
), a Boolean
cannot be passed to a method expecting Object
(s).
You can use the companion object scala.Boolean
to "box" (in Java's sense, of course) a boolean
into java.lang.Boolean
:
JavaClass.varargsMethod(Boolean.box(true))
The other AnyVal
classes have corresponding box
methods (e.g. Int.box
). There are also unbox
methods to do the opposite.
A more complicated use case:
JavaClass.varargsMethod(Seq(1, 2, 3, 4).map(Int.box): _*) // passes 1, 2, 3, 4
I don't know when these were added to the standard library, but with these you don't have to use the implementation classes of scala.runtime.*
.
Note, with Scala version 2.13.x, this works out-of-the-box (no pun) without having to manually box the value.
Probably can file a bug about it. It seems like it should throw an exception in both cases or neither. Not sure it's something that will ever be fixed as it probably is caused by some cleverness in the implementation of varargs that prevents the boxing from taking place.
精彩评论